📌 Goal
- 생성자의 핵심 개념과 기본 문법을 이해하고 사용할 수 있다.
- 생성자가 메서드와 구분되는 두 가지 차이를 이해하고 설명할 수 있다.
- 메서드 오버로딩이 생성자에서 어떻게 구현될 수 있는 지 확인하고 이해할 수 있다.
- 기본 생성자와 매개변수가 있는 생성자의 차이를 설명할 수 있다.
- this 와 this() 의 차이에 대해 설명할 수 있다.
📌 생성자(Constructor)
객체를 생성하는 역할을 하는 클래스의 구성 요소로서, 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드
new키워드를 사용하여 객체를 생성할 때에 호출되는 것이 사실 바로 이 생성자다. 그러나 생성자라는 이름에서 생성자가 인스턴스를 생성하는 역할을 하는 것은 아니다. 인스턴스 생성을 담당하는 것은 new키워드이며, 생성자는 인스턴스 변수들을 초기화하는 데 사용되는 특수한 메서드이다.
✔️ 생성자(Constructor)와 메서드(Method)의 차이
생성자의 이름은 반드시 클래스의 이름과 같아야 한다.
만약 클래스 이름과 생성자의 이름이 다르다면 그 메서드는 더이상 생성자로서의 기능을 수행할 수 없다.
생성자는 리턴 타입이 없다.
메서드에서 리턴 값이 없을 때 표시하는 void 키워드를 사용하지 않는다. 그 이유는 무언가를 ‘리턴하지 않는다’를 의미하는 void와는 다르게 생성자는 아예 리턴 타입 자체가 존재하지 않기 때문이다.
클래스명(매개변수) { // 생성자 기본 구조
...생략...
}
먼저 클래스명과 같은 이름의 생성자명을 작성해주고 리턴 타입이 없기 때문에 리턴 타입에는 아무것도 적지 않는다. 매개변수는 있을 수도 있고 없을 수도 있다.
❗️ 기억해야할 점
생성자도 메서드 오버로딩과 같이 오버로딩이 가능하므로 한 클래스 내에 여러 개의 생성자가 존재할 수 있다.
스타크래프트의 예를 들면 일반 유닛 탱크와 영웅 유닛 탱크의 예로 들어볼 수 있다. 동일한 탱크 클래스를 조건에 따라 생성자를 오버로딩해서 다형성을 줄 수 있다.
public class ConstructorExample {
public static void main(String[] args) {
Tank tank1 = new Tank();
Tank tank2 = new Tank("영웅유닛 탱크");
}
}
class Tank {
Tank() { // (1) 생성자 오버로딩
System.out.println("일반유닛 탱크");
}
Tank(String str) { // (2)
System.out.println("영웅유닛 탱크");
}
}
📌 기본생성자(Default Constructor) vs 매개변수가 있는 생성자
✔️ 기본생성자(Default Constructor)
기본 생성자(Default Constructor)는 매개변수가 없는 생성자를 의미한다.
모든 클래스에는 반드시 하나 이상의 생성자가 존재해야 한다. 생성자를 따로 만들지 않아도 정상적으로 인스턴스를 만들 수 있는 이유는 만약 생성자가 클래스 안에 포함되어 있지 않은 경우에는 자바 컴파일러가 기본 생성자를 자동으로 추가해주기 때문이다. 만약에 생성자가 이미 추가되어있는 경우 기본생성자가 아니라 이미 추가되어 있는 생성자를 기본으로 사용한다.
클래스명(){} //기본 생성자
DefaultConst(){} // 예시) DefaultConst 클래스의 기본 생성자
✔️ 매개변수가 있는 생성자
매개변수가 있는 생성자는 메서드처럼 매개변수를 통해 호출 시에 해당 값을 받아 인스턴스를 초기화하는 데 사용한다.
고유한 특성을 가진 인스턴스를 계속 만들어야하는 경우 인스턴스마다 각기 다른 값을 가지고 초기화할 수 있어서 매우 유용하다.
📌 this() vs this 키워드
✔️ this()
this() 메서드는 자신이 속한 클래스에서 다른 생성자를 호출하는 경우에 사용한다.
메서드의 호출에서 같은 클래스 안에 메서드들끼리 서로 호출할 수 있었던 것처럼 생성자도 tihs() 메서드를 통해 상호 호출이 가능하다.
this()메서드를 사용하기 위해서 크게 두 가지의 문법요소를 충족해야한다.
첫 째, this() 메서드는 반드시 생성자의 내부에서만 사용할 수 있다.
둘 째, this() 메서드는 반드시 생성자의 첫 줄에 위치해야 한다.
public class Test {
public static void main(String[] args) {
Example example = new Example();
Example example2 = new Example(5);
}
}
class Example {
public Example() {
System.out.println("Example의 기본 생성자 호출!");
};
public Example(int x) {
this();
System.out.println("Example의 두 번째 생성자 호출!");
}
}
//Output
Example의 기본 생성자 호출!
Example의 기본 생성자 호출!
Example의 두 번째 생성자 호출!
Example클래스는 두 개의 생성자를 가지고 있다. 하나는 매개변수가 필요하지 않은 기본 생성자이고, 다른 하나는 int 타입의 매개변수를 받고 있는 생성자이다. 그리고 두 번째 생성자 내부의 첫 번째 줄에 this() 메서드가 포함되어 있다.
이제 Example클래스를 기반으로 만들어지는 인스턴스를 생성하면, 첫 번째 생성자가 호출되고 그 결과로 Example의 기본 생성자 호출!이라는 문구가 출력된다. 다음으로 두 번째 생성자를 사용하여 객체를 만드는 과정에서 생성자가 호출되면 먼저 this()메서드가 출력되어 다시 첫 번째 기본생성자가 호출되고, 그 다음으로 Example의 두 번째 생성자 호출!이라는 문구가 출력된다.
✔️ this 키워드
this 키워드는 변수를 구분해주기 위한 용도로 사용된다.
인스턴스 변수와 매개변수를 이름만으로는 구분하기가 어려워지는 문제가 발생하게 되는데 이를 해결하기 위해 this 키워드를 사용한다.
public class ConstructorExample {
public static void main(String[] args) {
Car car = new Car("Model X", "빨간색", 250);
System.out.println("제 차는 " + car.getModelName() + "이고, 컬러는 " + car.getColor() + "입니다.");
}
}
class Car {
private String modelName;
private String color;
private int maxSpeed;
public Car(String modelName, String color, int maxSpeed) {
this.modelName = modelName;
this.color = color;
this.maxSpeed = maxSpeed;
}
public String getModelName() {
return modelName;
}
public String getColor() {
return color;
}
}
//Output
제 차는 Model X이고, 컬러는 빨간색입니다.
인스턴스 변수로 modelName, color, 그리고 maxSpeed가 선언되어 있는데, 동시에 생성자의 매개변수로 modelName, color, maxSpeed가 정의되어 있다. 만약에 위의 코드에서, this.modelName = modelName 대신 modelName = modelName라고 작성하면 둘 다 지역변수로 간주되고 만다. 이때, 이 변수들의 구분을 해주기 위한 용도로 주로 사용되는 방법이 바로 this 키워드이다.
this는 인스턴스 자신을 가리키며, 우리가 참조변수를 통해 인스턴스의 멤버에 접근할 수 있는 것처럼 this를 통해서 인스턴스 자신의 변수에 접근할 수 있다. 예를 들면, 현재 Car클래스의 modelName이라는 인스턴스 필드를 클래스 내부에 출력하고자 한다면 원래는 System.out.println(this.modelName)이런 방식으로 작성해주어야 한다.
댓글