큐가 문제를 내줬다. 제인의 리뷰에 달려있던 내용인데, 아래의 실행결과는 YXYZ 다. 부끄럽지만 처음에는 super 생략을 생각하지 못했고, 이후에는 실행 순서가 정확히 이해가 되지 않았다.
class X {
Y b = new Y();
X() {
System.out.print("X");
}
}
class Y {
Y() {
System.out.print("Y");
}
}
class Z extends X {
Y y = new Y();
Z() {
System.out.print("Z");
}
public static void main(String[] args) {
new Z();
}
}
해설을 읽어보니 static, super(), 필드 초기화, 생성자 블럭 실행의 순서로 실행된다고 한다. 그럼에도 정확히 이해가 안돼서 컴파일 시 바이트 코드가 그렇게 바뀐다는 글에서 힌트를 얻어 디컴파일을 해봤다.
요약하자면, 컴파일하면
그런데, 생성자 블록에 합쳐질때, 생성자에 작성된 소스보다 상위에 합쳐진다. 즉, 생성자에 직접 작성한 코드는 나중에 실행된다.
class X {
Y b;
X();
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #12 // class Y
8: dup
9: invokespecial #14 // Method Y."<init>":()V
12: putfield #15 // Field b:LY;
15: getstatic #17 // Field java/lang/System.out:Ljava/io/PrintStream;
18: ldc #23 // String X
20: invokevirtual #25 // Method java/io/PrintStream.print:(Ljava/lang/String;)V
23: return
}
class Y {
Y();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream;
7: ldc #16 // String Y
9: invokevirtual #18 // Method java/io/PrintStream.print:(Ljava/lang/String;)V
12: return
}
class Z extends X {
Y y;
Z();
Code:
0: aload_0
1: invokespecial #10 // Method X."<init>":()V
4: aload_0
5: new #12 // class Y
8: dup
9: invokespecial #14 // Method Y."<init>":()V
12: putfield #15 // Field y:LY;
15: getstatic #17 // Field java/lang/System.out:Ljava/io/PrintStream;
18: ldc #23 // String Z
20: invokevirtual #25 // Method java/io/PrintStream.print:(Ljava/lang/String;)V
23: return
public static void main(java.lang.String[]);
Code:
0: new #1 // class Z
3: invokespecial #37 // Method "<init>":()V
6: return
}
Powered with by Gatsby 2.0