생성자는 인스턴스의 초기화를 위한 특별한 메소드이다.
클래스를 공부할 때 Tv 클래스의 인스턴스를 생성하는 법을 배웠다.
Tv t = new Tv();
이 때, new 연산자 뒤에 오는 Tv()가 생성자이다.
생성자라는 용어 때문에 인스턴스 생성을 생성자가 하는 줄 알지만
생성자는 그저 인스턴스 변수들의 초기화를 위한 메소드이다.
인스턴스의 생성은 new 연산자가 한다.
Tv t = new Tv();
- 연산자
new에 의해 메모리(Heap)에 Tv 클래스의 인스턴스 생성- Tv( ) 생성자가 호출되어 수행
new의 결과로 생성된 Tv 인스턴스의 주소가 반환되어 변수 t에 저장
생성자 역시 메소드처럼 클래스 내에 선언되며, 구조도 메소드와 유사하지만 몇 가지 조건이 있다.
생성자가 리턴 값이 없지만 '리턴값이 없음'을 뜻하는 void를 사용하지는 않고, 아무 것도 적지 않는다.
생성자도 오버로딩이 가능하기 때문에 여러 개의 생성자가 있을 수 있다.
class Tv {
int size;
String color;
Tv() { ... } // 매개변수가 없는 생성자
Tv(int s, String c) { ... } // 매개변수가 있는 생성자
}
모든 클래스에서는 생성자가 반드시 하나 이상 정의되어 있어야 한다.
그러나 생성자를 정의하지 않고도 정상적으로 프로그램이 실행이 되었는데, 그 이유는 컴파일러가 제공하는 기본 생성자 때문이다.
컴파일할 때, 소스파일( *. java )의 클래스에 생성자가 하나도 정의되어 있지 않다면 컴파일러가 자동적으로 클래스이름( ) { }의 형태로 기본 생성자를 추가한다.
class A {
int a;
}
class B {
int b;
B(int x) { b = x; }
}
class Main {
public static void main(String[] args) {
A a = new A();
B b = new B(); // 컴파일 에러
위와 같이 실행한다면 B 인스턴스를 생성할 때 컴파일 에러가 발생한다.
그 이유는 B의 클래스에는 int형 매개변수를 받는 생성자가 이미 있기 때문에
기본 생성자 는 추가되지 않기 때문이다.
기본 생성자가 컴파일러에 의해 추가되는 경우는
클래스에 정의된 생성자가 없을 때이다.
class Tv {
int size;
String color;
Tv() { } // 매개변수가 없는 생성자
Tv(int s, String c) { // 매개변수가 있는 생성자
size = s;
color = c;
}
}
class Main {
public static void main(String[] args) {
// 매개변수 없는 생성자 사용 및 필드 따로 초기화
Tv t = new Tv();
t.size = 65;
t.color = "Black";
// 매개변수 있는 생성자 사용 + 필드 동시 초기화
Tv v = new Tv(65, "Black");
메소드가 메소드를 호출할 수 있는 것처럼, 생성자도 생성자를 호출할 수 있다.
단, 두 가지 조건을 만족시켜야 한다.
Tv(int size) {
this(size, "Blue");
color = "Black";
}
위의 코드처럼 this( )를 통해 다른 생성자를 호출해야하고
생성자 호출이 맨 첫 줄에 와야 한다.
생성자 호출이 첫 줄에 와야 하는 이유는 초기화 도중 다른 생성자를 호출하여 필드 초기화가 다시 진행되면 이전에 행한 초기화가 무의미해질 수 있기 때문이다.
class Car {
String color;
String gearType;
int door;
// Car() {
// color = "white";
// gearType = "auto";
// door = 4;
// }
Car() {
this("white", "auto", 4);
}
Car(String c, String g, int d) {
color = c;
gearType = g;
door = d;
}
인스턴스 변수들의 디폴트 값이 있다면 이런 방식으로 유기적으로 연결하여 사용할 수 있다.
this( )와는 완전히 다른 문법이다.
this( )는 생성자 이고, this 는 참조 변수 이다.
바로 위의 코드에서 color = c 부분은 생성자의 매개변수로 선언된 변수 c의 값을
인스턴스 변수 color 에 저장한다. 이 때에 매개변수와 인스턴스변수는 이름만으로 구분되기에 문제가 없다.
하지만, 만약 매개변수의 이름도 color 로 지정된다면 두 변수가 구별이 되지 않는다.
이런 경우 인스턴스 변수 앞에 this를 사용하면 된다.
Car(String color, String gearType, int door) {
this.color = color;
this.gearType = gearType;
this.door = door;
}
this가 숨어있다