생성자(Constructor)
생성자란?
- 생성자는 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드이다.
- 따라서 인스턴스 변수의 초기화 작업에 주로 사용되며, 인스턴스 생성 시에 실행되어야 할 작업을 위해서도 사용된다.
- 생성자 역시 메서드처럼 클래스 내에 선언되며, 구조도 메서드와 유사하지만 리턴 값이 없다는 점이 다르다
- 그렇다고 해서 생성자 앞에 리턴값이 없음을 뜻하는 키워드 void를 사용하지는 않는다.
- 생성자의 조건은 다음과 같다
- 생성자의 이름은 클래스 이름과 같아야 한다.
- 생성자는 리턴 값이 없다.
- 생성자는 다음과 같이 정의한다.
- 생성자도 오버로딩이 가능하므로 하나의 클래스에 여러개의 생성자가 존재할 수 있다.
클래스 이름(타입 변수명, 타입 변수명, ...) {
// 인스턴스 생성 시 수행될 코드,
// 주로 인스턴스 변수의 초기화 코드를 적는다.
}
class Card {
Card() { // 매개 변수가 없는 생성자.
...
}
card(String k, int num) { // 매개 변수가 있는 생성자.
...
}
...
}
- 연산자 new가 인스턴스를 생성하는 것이지 생성자가 인스턴스를 생성하는 것이 아니다.
- 생성자는 단순히 인스턴스 변수들의 초기화에 사용된다.
- Card 클래스의 인스턴스를 생성하는 코드를 예로 들어, 수행되는 과정을 단계별로 나누어보면 다음과 같다.
- Card c = new Card();
- 연산자 new에 의해서 메모리(heap)에 Card 클래스의 인스턴스가 생성된다.
- 생성자 Card()가 호출되어 수행된다.
- 연산자 new의 결과로 생성된 Card 인스턴스의 주소가 반환되어 참조변수 c에 저장된다.
- Card c = new Card();
- 인스턴스를 생성하기 위해 사용했던 클래스이름()이 생성자였다.
기본 생성자(default constructor)
- 모든 클래스에는 반드시 하나 이상의 생성자가 정의되어 있어야 한다.
- 클래스에 생성자를 정의하지 않고도 인스턴스를 생성할 수 있었던 이유는 컴파일러가 제공하는 기본 생성자 덕분이었다.
- 컴파일 할 때 소스파일의 클래스에 생성자가 하나도 정의되지 않은 경우, 컴파일러는 자동적으로 기본 생성자를 추가하여 컴파일한다.
- 클래스이름() { }
- Card() { }
- 클래스의 접근 제어자가 public 인 경우에는 기본 생성자로 public 클래스이름() { }이 추가된다.
- 컴파일러가 기본 생성자를 자동으로 추가해주는 경우는 클래스 내에 생성자가 하나도 없을 때 뿐이다.
매개 변수가 있는 생성자
-
생성자도 메서드처럼 매개변수를 선언하여 호출 시 값을 넘겨받아서 인스턴스의 초기화 작업에 사용할 수 있다.
- 매개 변수가 있는 생성자를 사용한다면 인스턴스를 생성하는 동시에 원하는 값으로 초기화를 할 수 있게 된다.
- 매개 변수를 갖는 생성자를 사용하는 것이 코드를 보다 간결하고 직관적으로 만든다.
생성자에서 다른 생성자 호출하기 - this(), this
- 생성자 간에도 서로 호출이 가능하다.
- 단 두 조건을 만족시켜야 한다.
- 생성자의 이름으로 클래스이름 대신 this를 사용한다.
- 한 생성자에서 다른 생성자를 호출할 때는 반드시 첫 줄에서만 호출이 가능하다.
- 단 두 조건을 만족시켜야 한다.
- 생성자에서 다른 생성자를 첫 줄에서만 호출이 가능하도록 한 이유는 생성자 내에서 초기화 작업 도중에 다른 생성자를 호출하게 되면 호출된 다른 생성자 내에서도 멤버 변수들의 값을 초기화를 할 것이므로 다른 생성자를 호출하기 이전의 초기화 작업이 무의미해질 수 있기 때문이다.
- 생성자의 매개변수로 인스턴스 변수들의 초기값을 제공받는 경우가 많기 때문에 매개변수와 인스턴스 변수의 이름이 일치하는 경우가 자주 있다.
- 이때 매개 변수 이름을 다르게 하는 것보다 this를 사용하여 구별되도록 하는 것이 의미가 더 명확하고 이해하기 쉽다.
- this는 참조변수로 인스턴스 자신을 가리킨다.
- this를 사용할 수 있는 것은 인스턴스 멤버 뿐이다.
- Static 메서드(클래스 메서드)에서는 인스턴스 멤버들을 사용할 수 없는 것처럼, this 역시 사용할 수 없다.
- static 메서드는 인스턴스를 생성하지 않고도 호출될 수 있기 때문에 static메서드가 호출된 시점에 인스턴스가 존재하지 않을수도 있기 때문이다.
생성자를 이용한 인스턴스의 복사
- 현재 사용하고 있는 인스턴스와 같은 상태를 갖는 인스턴스를 하나 더 만들고자 할 때 생성자를 이용할 수 있다.
- 두 인스턴스가 같은 상태를 갖는다는 것은 두 인스턴스의 모든 인스턴스 변수(상태)가 동일한 값을 갖고 있다는 것을 뜻한다.
- 하나의 클래스로부터 생성된 모든 인스턴스의 메서드와 클래스 변수는 서로 동일하기 때문에, 인스턴스 간의 차이는 인스턴스 변수 뿐이다.
- 매개변수로 넘겨진 참조변수가 가리키는 인스턴스의 인스턴스변수의 값을 인스턴스 자신으로 복사한다.
Car(Car c) {
color = c.color;
gearType = c.gearType;
door = c.door;
}
Car(Car c) {
//Car(String color, String gearType, int door)
this(c.color, c.gearType, c.door);
}