JAVA

클래스와 객체

saniii 2022. 12. 29. 21:34

객체 지향 언어의 특성

  • 캡슐화, Encapsulation
    • 객체를 캡슐로 싸서 내부를 보호하고 볼 수 없게 하는 것
    • 객체는 캡슐화가 기본 원칙이지만 외부와의 접속을 위해 몇 부분만 공개 노출한다.
    • 자바에서의 객체는 클래스라는 캡슐화를 사용하며, 필드(멤버 변수)와 메소드(멤버 함수)로 구성된다.
  • 상속, Inheritance
    • 자식 클래스가 부모 클래스의 속성을 물려받고 기능을 추가하여 확장(extends)하는 개념
    • 부모 클래스를 슈퍼 클래스라고 부르고 자식 클래스를 서브 클래스라고 부른다.
    • 상속은 슈퍼 클래스의 필드와 메소드를 물려받아 코드를 재사용함으로써 코드 작성에 드는 시간과 비용을 줄인다.
  • 다형성, Polymorphism
    • 같은 이름의 메소드가 클래스 혹은 객체에 따라 다르게 동작하도록 구현되는 것
      • 동물 클래스를 상속받은 고양이, 강아지 클래스의 메소드, speak()은 각자 다른 울음소리를 출력한다.
    • 메소드 오버라이딩
      • 슈퍼 클래스에서 구현된 메소드를 서브 클래스에서 동일한 이름으로 자신의 특징에 맞게 재정의한 것
    • 메소드 오버로딩
      • 클래스 내에서 이름이 같지만 서로 다르게 동작하는 메소드를 여러 개 만드는 것

객체 지향 언어의 목적

  • 소프트웨어의 생산성 향상
    • 상속을 통해 이미 작성된 코드를 재사용하기 쉬우며, 부분 수정을 통해 소프트웨어를 다시 만드는 부담을 줄일 수 있다.
  • 실세계에 대한 쉬운 모델링

객체 지향 프로그래밍

→ 실제 세상의 물체를 객체로 표현하고 객체들의 관계, 상호 작용을 설계한 뒤, 각 객체를 클래스로 작성

자바 클래스 만들기

  • 클래스
    • 객체를 만들어내기 위한 설계도, 틀
  • 객체 , 클래스의 인스턴스
    • 클래스 모양 그대로 생성된 실체
    • 객체들은 클래스의 모양대로 모두 동일한 속성을 가지지만 자신만의 고유한 값을 가짐으로써 구분된다.
    클래스 선언하기
public class Circle {
	public int radius;
	public String name;

	public Circle() {}
	public double getArea() {
		return 3.14 * radius * radius;
	}
}
  • 필드
  • 객체 내에 값을 저장할 멤버 변수
  • 접근 지정자
  • 이 클래스에 접근 허용 범위를 지정
  • 메소드
  • 함수, 객체의 행동을 구현한다.
  • 생성자, constructor
  • 클래스와 동일한 이름의 메소드

new 연산자와 객체 생성, 레퍼런스 변수

public static void main (String args[]) {

	Circle pizza;           
  // Circle 객체에 대한 레퍼런스 변수 pizza 선언
	pizza = new Circle();   
	// Circle 객체 생성 

	pizza.radius = 10;
	pizza.name = "피자";
	double area = pizza.getArea();
}

라인 3처럼 레퍼런스 변수만 선언했을 때는 객체에 대한 메모리가 할당되어 있지 않다. (객체 생성 X)

라인 5와 같이 new를 통해 메모리를 할당해야 객체 생성이 이루어진다.

<aside> 💡 [ 레퍼런스 변수 ] c++에서는 Circle pizza; 자체만으로 객체가 생성되지만 자바에서는 레퍼런스 변수를 선언만 한다는 차이점이 있다. 객체를 생성하고 싶으면 new 키워드를 사용해야 한다.

</aside>

  • new 연산자에 의해 객체가 생성되는 과정
    1. Circle 타입 크기의 메모리 할당
    2. Circle() 생성자 코드 실행

생성자 , constructor

객체가 생성될 때 초기화를 위해 실행되는 메소드, 생성자는 객체가 생성되는 순간에 자동으로 호출된다.

  1. 생성자의 이름은 클래스 이름과 동일하다.
  2. 생성자의 이름은 반드시 클래스 이름과 동일하게 작성해야 한다.
  3. 생성자는 오버로딩할 수 있다.
  4. 생성자는 new를 통해 객체를 생성할 때 한 번만 호출된다.
  5. 객체 생성은 반드시 new를 통해서만 이루어지며, 생성자는 이 때 자동으로 한번만 호출된다. 아무때나 호출할 수 없
  6. 생성자에 리턴 타입을 지정할 수 없다.
  7. 생성자는 어떤 값도 리턴하지 않기 때문에 생성자 자체에 리턴타입을 지정할 수는 없지만 return ; 을 사용할 수는 있다. return 문을 사용하면 생성자의 실행을 끝내고 호출한 곳으로 돌아가게 되므로 생성자의 실행을 끝내고 싶은 곳에서 return 문을 사용하면 된다.
  8. 생성자의 목적은 객체가 생성될 때, 필요한 초기 작업을 위함이다.
  9. 생성자는 객체가 생성될 때, 필드 초기화, 필요한 메모리 확보, 파일 열기, 네트워크 연결 등 객체가 활동하기 전에 필요한 초기 준비를 하는데 이용된다.

[ 기본 생성자 ]

객체가 생성될 때는 반드시 생성자가 필요하기 때문에 개발자가 생성자를 만들어놓지 않은 경우에는 자바 컴파일러가 기본 생성자를 자동으로 생성하여 컴파일 한다. 기본 생성자는 매개 변수와 실행모드가 없어 아무일도 하지 않고 객체만 생성한다.

대신 생성자가 하나라도 존재하는 경우에는 기본 생성자를 생성해주지 않기 때문에 원한다면 따로 작성하여야 한다.

this 레퍼런스

객체 자신을 가리키는 레퍼런스, 현재 실행되고 있는 메소드가 속한 객체에 대한 레퍼런스

  • this는 컴파일러에 의해 자동으로 관리되고 있으므로 개발자는 this를 사용하기만 하면 된다.

[ this의 필요성 ]

클래스 네에서 멤버 변수에 접근할 때는 굳이 this를 붙일 필요가 없다.

  1. 매개변수의 이름은 그 자체로 용도를 나타내기 때문에 적합한 이름을 붙이는 것이 중요한데 이러다보니 매개 변수의 이름을 멤버 변수의 이름으로 붙여야 하는 경우가 많이 생긴다. 이때 this를 사용하여 해결할 수 있다.
public Circle(int radius) { this.radius = radius }
// this.radius -> 멤버 변수
// radius -> 매개 변수 
  1. 메소드가 객체 자신의 레퍼런스를 리턴해야할 때 사용할 수 있다.
public Circle getMe() { return this; }

[ this(), 다른 생성자 호출하기 ]

클래스 내에서 생성자가 다른 생성자를 호출할 때 사용한다.

  • this()는 반드시 생성자 코드에서만 사용할 수 있다.
  • this()는 반드시 같은 클래스 내 다른 생성자를 호출할 때 사용된다.
  • this()는 반드시 생성자의 첫 번째 문장이 되어야 한다.

객체 치환

= 연산자로 객체를 치환할 때 → 객체의 치환은 객체를 복사하는 것이 아니다.

Circle ob1 = new Circle(1); //1
Circle ob2 = new Circle(2); //2

s = ob2;                    //3

ob1 = ob2;                  //4

라인 1, 2 후 라인 3을 실행하면 s(레퍼런스 변수)는 ob2와 같은 객체를 가리키게 된다. 역시 라인 4를 실행하면 레퍼런스 변수 ob1은 ob2가 가리키는 객체를 같이 가리키게 되고 원래 ob1이 가리키던 객체는 아무도 가리키지 않게 되어 프로그램에서 접근할 수 없는 가비지(garbage가 된다.) // 가비지는 자바 가상 기계에 의해 자동으로 수거되어 재사용된다.

객체 배열

자바에서는 기본 타입 데이터뿐만 아니라 객체를 원소로 하는 객체 배열도 만들 수 있는데 C/C++과 달리 객체에 대한 레퍼런스를 원소로 갖는 배열이다.

Circle [] c;
// Circle 배열에 대한 레퍼런스 변수 c 선언
c = new Circle[5];
// 레퍼런스 배열 생성

for (int i = 0; i < c.length; i++) {
	c[i] = new Circle(i);
	// 배열의 각 원소 객체 생성
}

// 201 페이지 그림 넣고 싶다.

  1. 배열에 대한 레퍼런스 선언
  2. 레퍼런스 변수를 선언만 할 뿐 배열을 생성하는 것은 아니다. 배열의 원소 개수를 지정하면 컴파일 오류난다.
  3. 레퍼런스 배열 생성
  4. 배열의 원소, 레퍼런스를 생성한다. 아직 Circle 객체들이 존재하는 것은 아니다.
  5. 원소 객체 생성
  6. Circle의 객체를 하나씩 생성하여 배열 c[]의 각 레퍼런스에 대입한다.
  • 배열 c의 i번째 원소에 접근하기 위해서는 c[i] 레퍼런스를 사용하면 된다.

메소드 활용

메소드 : 클래스의 멤버 함수

public int getSum(int i, int j) {
	return i + j;
}

인자 전달

자바의 메소드 호출 시 인자 전달 방식은 “값에 의한 호출, call-by-value” 이다.

호출하는 실인자의 값이 복사되어 메소드의 매개 변수에 전달된다.

  1. 기본 타입의 값이 전달되는 경우 | byte, char, short, int, float, long, double, boolean
  2. → call-by-value
  3. 클래스 객체가 전달되는 경우ㄴㅇㅁ러ㅏㅗ
  4. → call-by-reference
  5. 배열이 전달되는 경우adskfjh
  6. → call-by-reference

static 멤버

| | non-static 멤버 인스턴스 멤버 | static 멤버 클래스 멤버 | | --- | --- | --- | | 선언 | | | | 공간적 특성 | - 객체마다 별도로 존재한다. | - 클래스당 하나씩 생성된다.

  • static 멤버는 객체 내부가 아닌 별도의 공간(클래스 코드가 적재되어 있는 메모리)에 생성된다. | | 시간적 특성 | - 객체 생성시에 인스턴스 멤버도 생성된다.
  • 객체가 생길 때 멤버도 생성
  • 객체 생성 후 멤버 사용 가능
  • 객체가 사라지면 멤버도 사라진다. | - 클래스 로딩 시에 멤버가 생성된다.
  • 객체가 생기기 전에 이미 생성된다.
  • 따라서 객체가 생기기 전에도 사용할 수 있다.
  • 객체가 사라져도 static멤버는 사라지지 않는다.
  • 프로그램이 종료되면 사라진다. | | 공유의 특성 | 공유되지 않으며 멤버는 객체 내의 각각의 공간에 유지된다. | 동일한 클래스의 모든 객체들에 의해 공유된다. |

static 멤버, 메소드는 객체 레퍼런스 변수를 통해서도 호출할 수 있지만 클래스 이름 자체를 사용해서도 호출할 수 있다.

static 멤버는 객체가 아닌 클래스마다 하나씩 존재하기 때문이다.

static의 활용

  1. 전역 변수와 전역 함수를 만들 때 활용한다.
  2. 공유 멤버를 만들고자 할 때 사용한다.

제약 조건

  1. static 메소드는 static 멤버만 접근할 수 있다.
  2. static 메소드는 객체가 생성되기 전에도 사용할 수 있기 때문에 동일하게 객체가 생성되기 전에 이미 만들어질 수 있는 static 멤버만 접근할 수 있다.
  3. static 메소드는 this를 사용할 수 없다.
  4. 역시 static 메소드는 객체가 생성되기 전에도 사용할 수 있기 때문에 객체 자체를 가리키는 this 레퍼런스는 사용할 수 없다.

final

final + class

이 클래스를 상속받을 수 없음을 지정한다. → final 이 붙어 선언된 클래스는 자식 클래스를 만들 수 없다.

final + method

오버라이딩할 수 없는 메소드임을 선언한다. → 자식 클래스가 부모 클래스의 특정 메소드를 오버라이딩하지 못하고 무조건 그대로 상속받아 사용하게 하고 싶을 때 사용할 수 있다.

final + field

상수 선언, 상수 필드는 한 번 초기화되면 변경할 수 없다.

public static final 로 선언하면 프로그램 전체에서 사용할 수 있는 상수가 된다. ( 클래스명.상수 형식으로 모든 클래스에서 사용할 수 있다.)