Java 생성자 오버로딩: 실전 코드 예제로 이해하기
Java에서 생성자란?
생성자(Constructor)는 메모리 할당 직후 새로 생성된 객체를 초기화하는 특수한 메서드입니다. 객체의 필드를 원하는 값으로 설정하거나, 생략 시 기본값으로 설정합니다. 생성자 정의는 선택사항이며, 제공하지 않으면 컴파일러가 표준 기본값을 할당하는 기본 생성자를 제공합니다:
- 숫자 기본 타입(int, double 등) → 0
- char → '\0'
- 객체 참조 → null
이 튜토리얼에서 다룰 내용:
- 생성자 생성 규칙
- 생성자 오버로딩
- 생성자 체이닝
Java 생성자 생성 규칙
- 생성자 이름은 클래스 이름과 정확히 일치해야 함
- 반환 타입을 가질 수 없음,
void도 안 됨
예제 1 – 첫 번째 생성자
1단계: 다음 코드를 Java 에디터에 입력하세요.
class Demo {
int value1;
int value2;
Demo() {
value1 = 10;
value2 = 20;
System.out.println("Inside Constructor");
}
public void display() {
System.out.println("Value1 === " + value1);
System.out.println("Value2 === " + value2);
}
public static void main(String[] args) {
Demo d1 = new Demo();
d1.display();
}
}
2단계: 컴파일하고 실행. 출력:
Inside Constructor
Value1 === 10
Value2 === 20
Java 생성자 오버로딩
Java는 클래스가 서로 다른 매개변수 리스트를 가진 여러 생성자를 정의하는 것을 허용합니다. 컴파일러는 매개변수의 개수와 타입으로 구별합니다.
Account라는 클래스의 유효한 생성자들은 다음과 같을 수 있습니다:
Account(int a);
Account(int a, int b);
Account(String a, int b);
예제 2 – 오버로드된 생성자들
1단계: 다음 코드 입력.
class Demo {
int value1;
int value2;
/* Demo() {
value1 = 10;
value2 = 20;
System.out.println("Inside 1st Constructor");
} */
Demo(int a) {
value1 = a;
System.out.println("Inside 2nd Constructor");
}
Demo(int a, int b) {
value1 = a;
value2 = b;
System.out.println("Inside 3rd Constructor");
}
public void display() {
System.out.println("Value1 === " + value1);
System.out.println("Value2 === " + value2);
}
public static void main(String[] args) {
Demo d1 = new Demo();
Demo d2 = new Demo(30);
Demo d3 = new Demo(30, 40);
d1.display();
d2.display();
d3.display();
}
}
2단계: 컴파일하고 실행. 매개변수 있는 생성자를 추가한 후 기본 생성자 Demo()가 없어 에러 발생. 기본 생성자를 사용하려면 명시적으로 선언해야 함:
Demo() {
// 기본 초기화 또는 커스텀 로직
}
주석 처리된 블록을 주석 해제하고 재컴파일하면 프로그램이 정상 실행됩니다.
생성자 체이닝
서브클래스가 인스턴스화되면 슈퍼클래스 생성자가 먼저 실행됩니다. 이를 생성자 체이닝이라고 합니다.
예제 3 – 부모와 자식 간 체이닝
1단계: 아래 코드 복사.
class Demo {
int value1;
int value2;
Demo() {
value1 = 1;
value2 = 2;
System.out.println("Inside 1st Parent Constructor");
}
Demo(int a) {
value1 = a;
System.out.println("Inside 2nd Parent Constructor");
}
public void display() {
System.out.println("Value1 === " + value1);
System.out.println("Value2 === " + value2);
}
public static void main(String[] args) {
DemoChild d1 = new DemoChild();
d1.display();
}
}
class DemoChild extends Demo {
int value3;
int value4;
DemoChild() {
// super(5); // 주석 해제하여 오버로드된 부모 생성자 호출
value3 = 3;
value4 = 4;
System.out.println("Inside the Constructor of Child");
}
public void display() {
System.out.println("Value1 === " + value1);
System.out.println("Value2 === " + value2);
System.out.println("Value3 === " + value3);
System.out.println("Value4 === " + value4);
}
}
2단계: 프로그램 실행. 자식 생성자가 명시적으로 super()를 호출하지 않으므로 기본 Demo() 생성자가 먼저 실행됨. 예상 출력:
Inside 1st Parent Constructor
Inside the Constructor of Child
Value1 === 1
Value2 === 2
Value3 === 3
Value4 === 4
3단계: 오버로드된 부모 생성자 Demo(int a)를 호출하려면 자식 생성자 첫 줄에 super(5);를 배치. 주석 해제 후 재실행:
Inside 2nd Parent Constructor
Inside the Constructor of Child
Value1 === 5
Value2 === 0
Value3 === 3
Value4 === 4
특정 슈퍼클래스 생성자가 서브클래스 로직 전에 실행되어야 할 때 super(...) 사용은 필수입니다.