new
연산자와 함께 사용한다.생성자도 클래스 내에 선언되는 메소드이지만 다음 조건을 만족해야 생성자로 간주한다. 반환값이 없는 메소드이지만 void
라는 키워드를 사용하지 않는다. 그저 반환타입 자체를 사용하지 않는다.
생성자도 메소드이기 때문에 오버로딩이 가능하다. 그래서 매개변수가 있는 생성자를 정의하면 자동으로 기본 생성자가 생성되지 않는다. 이미 생성자가 정의되어 있기 때문이다. 따라서 매개변수가 있는 생성자를 정의했다면 반드시 기본 생성자를 정의해주어야 매개변수 없이 객체를 생성할 수 있다. 그렇지 않을 경우 에러가 발생한다.
다음 예제를 통해 생성자가 어떻게 사용되는지 구체적으로 이해해 보자. Car
클래스를 기본 생성자와 매개변수를 갖는 생성자를 오버로딩했고, Car
클래스로부터 생성자를 이용해 객체를 생성하고 객체의 멤버변수를 출력한 예제이다.
public class Car {
String name;
String maker;
int price;
// 기본 생성자를 정의한다.
public Car() {
}
// carName과 carMaker를 매개변수로 하는 생성자 메소드를 오버로딩했다.
public Car(String carName, String carMaker) {
name = carName;
maker = carMaker;
}
// carName, carMaker, carPrice를 매개변수로 하는 생성자 메소드를 오버로딩했다.
public Car(String carName, String carMaker, int carPrice) {
name = carName;
maker = carMaker;
price = carPrice;
}
}
public class CarApp {
public static void main(String[] args) {
String carName = "3-series";
String carMaker = "BMW";
// 3-series와 BMW를 인자로 전달하여 Car객체를 생성한다.
Car car = new Car(carName, carMaker);
System.out.println("이름: " + car.name);
System.out.println("제조사: " + car.maker);
System.out.println("가격: " + car.price);
}
}
출력
이름: 3-series
제조사: BMW
가격: 0
같은 이름의 메소드를 오버로딩했기 때문에 매개변수의 개수에 맞는 메소드가 자동으로 실행되었다. 객체의 멤버변수가 전달받은 인자로 초기화 되었다. 그러나 인자가 없던 price
는 기본값으로 초기화되었다.
앞서 언급했던 것처럼 매개변수가 있는 생성자를 정의하고 기본 생성자를 정의하지 않았을 때는 다음과 같은 에러가 발생한다.
말그대로 기본 생성자 Car()
가 정의되지 않았다는 의미이다.
위의 예제를 통해 생성자를 실행할 때 JVM이 수행하는 작업을 이해해보자.
Car car = new Car()
는 다음과 같은 과정으로 수행된다.
Car()
추가Car
객체 생성Car()
실행car
에 Car
객체의 주소값 대입this
키워드객체가 생성되면 그 객체 내부에 this
라는 이름을 가진 변수가 자동으로 생성된다. 변수 this
에는 해당 객체 자신의 주소값이 저장되어 있다.
따라서 this
키워드를 통해 해당 객체의 멤버 변수나 메소드에 접근할 수 있다.
this
참조변수객체를 생성한 후, 참조변수명.필드명
으로 객체의 멤버변수에 접근할 수 있다. 마찬가지로 this
를 이용해 this
를 포함하는 객체의 멤버변수에 접근할 수 있다. 클래스를 정의할 때, 메소드의 매개변수와 필드명을 구분하기 위해 사용한다.
this()
메소드한 생성자에서 다른 생성자를 호출할 때 사용한다. 반드시 생성자 내부에서만 사용 가능하며, 생성자의 실행문 중 첫 번째 줄에 위치해야한다.
this
키워드 예제다음의 예제는 위에서 다룬 예제를 this
키워드를 이용해 재구성한 것이다.
public class Car {
String name;
String maker;
int price;
// 기본 생성자이고 생성과 동시에 지정해둔 값으로 멤버변수를 초기화한다.
public Car() {
this("3-series", "BMW", 5000);
}
// 세 번째 생성자의 maker에 "BMW"를 인자로 전달한다.
public Car(String name, int price) {
this(name, "BMW", price);
}
// this를 통해 매개변수와 필드명을 구분했다.
public Car(String name, String maker, int price) {
this.name = name;
this.maker = maker;
this.price = price;
}
}
public class CarApp {
public static void main(String[] args) {
Car car1 = new Car();
Car car2 = new Car("5-series", 8000);
System.out.println("Car1 이름: " + car1.name);
System.out.println("Car1 제조사: " + car1.maker);
System.out.println("Car1 가격: " + car1.price);
System.out.println();
System.out.println("Car2 이름: " + car2.name);
System.out.println("Car2 제조사: " + car2.maker);
System.out.println("Car2 가격: " + car2.price);
}
}
출력
Car1 이름: 3-series
Car1 제조사: BMW
Car1 가격: 5000
Car2 이름: 5-series
Car2 제조사: BMW
Car2 가격: 8000
마찬가지로 매개변수의 개수에 따라 자동으로 메소드가 선택된다.
기본 생성자를 통해 생성한 Car1
은 이미 클래스에서 정의된 값으로 멤버변수가 초기화되었다.
Car2
는 "BMW"
를 인자로 전달받은 세 번째 생성자가 먼저 실행된 후 해당 객체의 생성자가 실행되었기 때문에 멤버변수 maker
가 "BMW"
로 초기화 되어있다.