생성자란?
인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드이다. 인스턴스 변수의 초기화 작업이나 인스턴스 생성 시에 실행되어야할 작업을 위해 사용된다.
클래스의 인스턴스를 생성할 때를 보면
Car car = new Car();
new 뒤에 Car(); 라는 메소드 모양의 코드가 나오는데 이것이 바로 생성자이다. 이때 생성자라는 이름때문에 생성자가 인스턴스를 만드는 것이라고 착각하면 안된다.
위의 코드가 수행되는 과정을 보면
1. 연산자 new에 의해 heap메모리에 Car 클래스의 인스턴스가 생성된다.
2. 생성자 Car()가 호출되어 수행된다.
3. 연산자 new의 결과로 생성된 Car 인스턴스의 주소가 반환되어 참조변수car에 저장된다.
생성자의 조건
1. 생성자의 이름은 클래스의 이름과 같아야 한다.
2. 생성자는 리턴값이 없다.
생성자 정의
클래스이름(타입 변수명, 타입 변수명, ... ){
// 인스턴스 생성 시 수행될 코드
(주로 인스턴스 변수의 초기화 코드를 입력한다.)
}
소스 코드를 통해 생성자 정의 방법을 알아보자.
class Car {
// 매개변수가 없는 생성자
Car() {
}
// 매개변수가 있는 생성자
Car(String color, String gearType, int door){
....
}
}
생성자도 오버로딩이 가능하므로 하나의 클래스에 여러개의 생성자가 존재할 수 있다.
생성자는 인스턴스 변수들의 초기화에 사용되는 조금 특별한 메서드일뿐 생성자가 인스턴스를 생성하는 것이 아니다.
기본 생성자
인스턴스를 생성할 때는 반드시 클래스 내에 정의된 생성자 중 하나를 선택하여 지정해주어야한다. 즉 클래스 내에는 반드시 하나 이상의 생성자가 있어야한다는 말이다.
그런데 우리는 클래스를 정의할때 생성자를 지정해주지 않아도 인스턴스가 생성된 것을 보았을 것이다.
그 이유는 "기본 생성자" 때문이다.
컴파일러는 컴파일 시 생성자가 하나도 정의되어있지 않은 경우 자동으로 아래와 같이 기본 생성자를 추가하여 컴파일한다.
class Car {
// 기본 생성자
Car() { }
}
인스턴스 초기화 작업이 필요하지 않다면 생성자를 따로 정의하지 않고 컴파일러가 제공하는 기본 생성자를 사용하는 것도 좋다. 만약 개발자가 생성자를 하나라도 정의한 경우 컴파일러는 기본 생성자를 자동으로 추가하지 않는다.
class Car {
// 매개변수가 있는 생성자
Car(String color, String gearType){
....
}
}
class Main {
public static void main(String args){
Car c1 = new Car(); // compile error 발생
Car c2 = new Car("blue", "auto");
}
}
위 예제를 실행하면 Car() 생성자가 정의되어 있지 않아 컴파일 에러가 발생한다.
생성자에서 다른 생성자 호출하기 this()
생성자 간에도 서로 호출이 가능하다. 단 몇가지 조건이 있다.
1. 생성자의 이름으로 클래스이름 대신 this()를 사용한다.
2. 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.
class Car01{
String color;
String gearType;
int door;
Car01(){
this("white", "auto", 4);
}
Car01(String color){
int door = 5;
this(color, "auto", 4); //다른 생성자를 첫 줄에 호출하지 않아 에러가 발생한다.
}
Car01(String color, String gearType, int door){
this.color = color;
this.gearType = gearType;
this.door = door;
}
}
같은 클래스 내의 생성자들은 서로 관계가 깊은 경우가 많아서 서로 호출하도록 하여 유기적으로 연결해주면 더 좋은 코드를 얻을 수 있다.
추가로 this와 this()는 비슷하게 생겼을 뿐 완전히 다른것이다. 혼동하지 말자.
this는 생성자의 매개변수의 이름과 인스턴스 변수들의 이름이 같은 경우 명확히 구별하기 위해 사용한다.
위의 코드에서 Car01(String color, String gearType, int door){ } 생성자를 보면 왼쪽의 this를 사용하여 왼쪽의 color는 인스턴스 변수의 color임을 나타낸다.
즉 'this'는 참조변수로 인스턴스 자신을 가리킨다. 'this'로 인스턴스변수에 접근할 수 있는 것이다. 이는 생성자를 포함한 모든 인스턴스메서드에는 'this'가 지역변수로 숨겨진채 존재하기 때문이다.
static메서드에서는 인스턴스 멤버들을 사용할 수 없는 것처럼 'this' 역시 사용할 수 없다.
마무리
생성자를 잘 활용하면 보다 간결하고 직관적인 객체지향적인 코드를 작성할 수 있다. 앞으로는 인스턴스를 생성할 때 다음 2가지 사항을 잘 고려해보자.
1. 클래스 - 어떤 클래스의 인스턴스를 생성할 것인가?
2. 생성자 - 선택한 클래스의 어떤 생성자로 인스턴스를 생성할 것인가?