[JAVA 기초]
개요
클래스의 구성 요소(필드, 메서드, 생성자, 내부 클래스) 중 생성자에 대해 알아보겠습니다.
학습 목표
- 생성자의 핵심 개념과 기본 문법을 이해한다.
- 생성자가 메서드와 구분되는 차이를 이해한다.
- 메서드 오버로딩이 생성자에서 어떻게 구현될 수 있는지 확인하고 이해한다.
- 기본 생성자와 매개변수가 있는 생성자의 차이를 설명한다.
- this와 this()의 차이에 대해서 이해한다.
생성자(Constructor)
우리는 앞서 new 키워드를 사용하여 객체를 생성할 때에 호출되는 것이 생성자입니다. 종종 생성자라는 이름에서 생성자가 인스턴스를 생성하는 역할을 한다는 오해가 발생하는데, 이것은 사실이 아닙니다. 인스턴스를 생성하는 것은 new 키워드이며, 생성자는 인스턴스 변수들을 초기화하는 데 사용되는 특수한 메서드라 할 수 있습니다.
생성자는 메서드와 비슷한 구조를 가지고 있지만 크게 두 가지 부분에서 차이가 있습니다.
- 생성자의 이름은 반드시 클래스의 이름과 같아야 합니다. 만약 클래스의 이름과 생성자의 이름이 다르다면 그 메서드는 생성자로서의 기능을 수행할 수 없습니다.
- 생성자는 리턴 타입이 없습니다. 하지만 메서드에서 리턴 값이 없을 때 표시하는 void 키워드를 사용하지 않습니다. 그 이유는 무언가를 '리턴하지 않는다'를 의미하는 void와 다르게 생성자는 리턴 타입 자체가 존재하지 않기 때문입니다.
이 두 가지 특징을 기억하면서 아래의 예시를 살펴봅시다.
public class Main{
public static void main(String[] args){
Constructor constructor1 = new Constructor();
Constructor constructor2 = new Constructor("Hello world");
Constructor constructor3 = new Constructor(5,10);
}
}
class Constructor {
Constructor() {
System.out.println("1번 생성자");
}
Constructor(String str) {
System.out.println("2번 생성자");
}
Constructor(int a, int b) {
System.out.println("3번 생성자");
}
}
// 출력 결과
1번 생성자
2번 생성자
3번 생성자
위의 예시에서 확인할 수 있듯이, 오버로딩을 활용하여 같은 이름을 가진 생성자 여러 개를 만들 수 있습니다.
여기서, 생성자의 모양에 따라서 객체를 생성하는 방법이 결정됩니다.
기본 생성자 vs 매개 변수가 있는 생성자
기본 생성자(Default Constructor)
지금까지 생성자의 존재를 모르고 new 키워드를 사용하여 생성자를 호출하여 객체를 만들었지만, 사실 모든 클래스에는
반드시 하나 이상의 생성자가 존재하여야합니다.
지금까지 생성자를 따로 만들지 않아도 정상적으로 인스턴스를 만들 수 있었던 이유는 만약 생성자가 클래스 안에
포함되어 있지 않는 경우에도 자바 컴파일러가 기본 생성자를 자동으로 추가해 줬기 때문입니다.
class car { // 예시) car 클래스의 기본 생성자
car(){}
}
위의 예시와 같이 컴파일러가 자동으로 추가해 주는 기본 생성자에는 매개 변수 등 아무런 내용이 없습니다.
그렇다면 생성자가 이미 추가되어 있는 경우에는 어떻게 될까요?
이 경우에는 기본생성자가 아니라 이미 추가되어 있는 생성자를 기본으로 사용하게 됩니다.
매개변수가 있는 생성자
매개변수가 있는 생성자는 메서드처럼 매개변수를 통해 호출 시에 해당 값을 받아 인스턴스를 초기화하는 데 사용됩니다.
고유한 특성을 가진 인스턴스를 계속 만들어야 하는 경우 인스턴스마다 각기 다른 값을 가지고 초기화할 수 있어서
유용합니다.
간단한 예시를 통해서 확인해 보겠습니다.
public class ConstructorExample {
public static void main(String[] args){
Phone p = new Phone("Gelaxy flip 3", "검은색", 512);
System.out.println("제 핸드폰은 " + c.getModelName() + "이고, 컬러는 " + c.getColor() + "입니다.");
}
}
class Phone {
private String modelName;
private String color;
private int volume;
public Phone(String modelName, String color, int volume){
this.modelName = modelName;
this.color = color;
this.volume = volume;
}
public Phone(modelName){
this.modelName = modelName;
}
public Phone(color){
this.color = color;
}
}
// 출력 결과
제 핸드폰은 Gelaxy flip 3이고, 컬러는 검은색입니다.
위의 예시를 보면 Phone 클래스의 인스턴스를 생성 시 매개변수가 있는 생성자를 사용하게 되면 인스턴스를 만든 후에 인스턴스의 필드값을 일일이 설정해 줄 필요 없이 생성과 동시에 원하는 값으로 초기화해 줄 수 있어서 편리합니다.
또한, 생성자의 모양에 따라서 객체를 생성하는 방법도 달라지게 됩니다. 앞의 기본 생성자의 경우에는 매개 변수가 없었기 때문에 원래 객체를 생성하는 방식으로 new 키워드와 생성자를 호출하면 되었지만, 현재는 기본 생성자가 매개 변수가 있기 때문에 매개 변수의 개수와 타입에 알맞게 생성자를 호출해주어야 합니다.
이렇듯 생성자의 특징을 잘 이해하면 보다 간결하고 직관적인 코드 작성이 가능합니다.
this vs this()
this()
앞선 글에서 메서드가 같은 클래스 안에서 서로 호출할 수 있었던 것처럼 생성자도 상호 호출이 가능합니다.
그리고 이를 위해 사용하는 것이 바로 this() 메서드입니다.
this() 메서드는 자신이 속한 클래스에서 다른 생성자를 호출하는 경우에 사용합니다.
예를 들면 만약 Phone 클래스의 생성자를 호출하는 것은 Phone()이 아니라 this이고, 그 효과는 Phone() 생성자를 호출하는 것과 동일합니다.
this() 메서드를 사용하기 위해서는 크게 두 가지의 문법요소를 만족해야만 합니다.
- this() 메서드는 반드시 생성자의 내부에서만 사용할 수 있습니다.
- this() 메서드는 반드시 생성자의 첫 줄에 위치해야 합니다.
위 두 가지 조건을 유념하면서 예시를 한번 살펴봅시다.
public class Test{
public static void main(String[] args){
Example example1 = new Example();
Example example2 = new Example(3);
}
}
class Example {
public Example(){
System.out.println("기본 생성자 호출");
}
public Example(int x) {
this();
System.out.println("두 번째 생성자 호출");
}
}
// 출력 결과
기본 생성자 호출
기본 생성자 호출
두 번째 생성자 호출
위 예시를 보면 Example 클래스를 기반으로 만들어지는 인스턴스를 생성하면, 첫 번째 생성자가 호출되고 결과로 '기본 생성자 호출'이라는 문구가 출력됩니다.
다음으로 두 번째 생성자를 사용하여 객체를 만드는 과정에서 생성자가 호출되면 먼저 this() 메서드를 통해 첫 번째 기본 생성자가 호출되고, 그다음으로 '두 번째 생성자 호출'이라는 문구가 출력됩니다.
this 키워드
앞선 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;
}
}
// 출력 결과
제 차는 Model X이고, 컬러는 빨간색입니다.
위 예제 코드를 보면 인스턴스 변수로 modelName, color, maxSpeed가 선언되어 있는데, 동시에 생성자에 같은 이름의 매개변수가 정의되어 있습니다.
이런 경우, 인스턴스 변수와 매개변수를 이름만으로는 구분하기가 어려워지는 문제가 발생하게 되는데, 이를 구분해 주기 위한 용도로 주로 사용되는 방법이 바로 this 키워드입니다.
this는 인스턴스 자신을 가리키며, 우리가 참조변수를 통해 인스턴스 멤버에 접근할 수 있는 것처럼 this를 통해서 인스턴스 자신의 변수에 접근할 수 있는 것입니다.
이번 글을 통해 생성자에 대해 알아보았습니다.
다음 글을 통해 클래스의 4가지 요소 중 마지막인 내부 클래스에 대해 알아보도록 하겠습니다
'JAVA > JAVA 이론' 카테고리의 다른 글
[JAVA 이론] 캡슐화(encapsulation) (0) | 2023.02.28 |
---|---|
[JAVA 이론] 상속(inheritance) (0) | 2023.02.27 |
[JAVA 이론] 내부 클래스(Inner Class) (0) | 2023.02.26 |
[JAVA 이론] 필드(Field)와 메서드(method) (0) | 2023.02.24 |
[Java 이론] 클래스와 객체 (0) | 2023.02.23 |