상속 관계의 인스턴스를 생성하면 결국 메모리 내부에는 자식과 부모 클래스가 각각 다 만들어진다. Child
를 만들면 부모인 Parent
까지 함께 만들어지는 것이다. 따라서 각각의 생성자도 모두 호출되어야 한다.
상속 관계를 사용하면 자식 클래스의 생성자에서 부모 클래스의 생성자를 반드시 호출해야 한다.
package extends1.super2;
public class ClassA {
public ClassA() {
System.out.println("ClassA 생성자");
}
}
ClassA
는 최상위 부모 클래스이다.package extends1.super2;
public class ClassB extends ClassA {
public ClassB(int a) {
super(); // 기본 생성자 생략 가능
System.out.println("ClassB 생성자 a = " + a);
}
public ClassB(int a, int b) {
super(); // 기본 생성자 생략 가능
System.out.println("ClassB 생성자 a = " + a + " b = " + b);
}
}
ClassB
는 ClassA
를 상속 받았다. 상속을 받으면 생성자의 첫 줄에 super(...)
를 사용해서 부모 클래스의 생성자를 호출해야 한다.예외
생성자 첫 줄에
this(...)
를 사용할 수 있다. 하지만super(...)
는 자식의 생성자 안에서 언젠가는 반드시 호출해야 한다.
super()
를 생략할 수 있다.super(...)
를 생략하면 자바는 부모의 기본 생성자를 호출하는 super()
를 자동으로 만들어준다.package extends1.super2;
public class ClassC extends ClassB {
public ClassC() {
super(10, 20);
System.out.println("ClassC 생성자");
}
}
ClassC
는 ClassB
를 상속 받았다. ClassB
에는 다음 두 생성자가 있다.ClassB(int a)
ClassB(int a, int b)
super(10, 20)
를 통해 부모 클래스의 ClassB(int a, int b)
생성자를 선택했다.ClassC
의 부모인 ClassB
에는 기본 생성자가 없다. 따라서 부모의 기본 생성자를 호출하는 super()
를 사용하거나 생략할 수 없다.package extends1.super2;
public class Super2Main {
public static void main(String[] args) {
ClassC classC = new ClassC();
}
}
실행해보면 ClassA
→ ClassB
→ ClassC
순서로 실행된다. 생성자의 실행 순서가 결과적으로 최상위 부모부터 실행되어서 하나씩 아래로 내려오는 것이다. 따라서 초기화는 최상위 부모부터 이루어진다. 왜냐하면 자식 생성자의 첫 줄에서 부모의 생성자를 호출해야 하기 때문이다.
new ClassC()
를 통해 ClassC
인스턴스를 생성한다. 이때 ClassC()
의 생성자가 먼저 호출되는 것이 맞다. 하지만 ClassC()
의 생성자는 가장 먼저 super(...)
를 통해 ClassB(...)
의 생성자를 호출한다. ClassB()
의 생성자도 부모인 ClassA()
의 생성자를 가장 먼저 호출한다.
ClassA()
의 생성자는 최상위 부모이다. 생성자 코드를 실행하면서 “ClassA 생성자”
를 출력한다.ClassA()
생성자 호출이 끝나면 ClassA()
를 호출한 ClassB(...)
생성자로 제어권이 돌아간다.ClassB(...)
생성자가 코드를 실행하면서 “ClassB 생성자 a=10 b=20”
을 출력한다. 생성자 호출이 끝나면 ClassB(...)
를 호출한 ClassC()
생성자로 제어권이 돌아간다.ClassC()
가 마지막으로 생성자 코드를 실행하면서 “ClassC 생성자”
를 출력한다.super(...)
를 호출해야 한다. 단 기본 생성자(super()
)인 경우 생략할 수 있다.코드 첫 줄에 this(...)
를 사용하더라도 반드시 한번은 super(...)
를 호출해야 한다.
package extends1.super2;
public class ClassB extends ClassA {
public ClassB(int a) {
this(a, 0);
System.out.println("ClassB 생성자 a = " + a);
}
public ClassB(int a, int b) {
super(); // 기본 생성자 생략 가능
System.out.println("ClassB 생성자 a = " + a + " b = " + b);
}
}
package extends1.super2;
public class Super2Main {
public static void main(String[] args) {
// ClassC classC = new ClassC();
ClassB classB = new ClassB(100);
}
}