동영상 강의 제작하다가 문득 내용이 괜찮을 듯 해서 블로그로 다시 정리합니다.
public class Book2 {
public void doA(){
System.out.println("book2 class doA method.... ");
}
}
라는 클래스가 있습니다.
그리고 이것을 상속받는 하위클래스가 있습니다.
public class Magazine2 extends Book2{
public void doA(){
System.out.println("Magazine2 class doA method.... ");
}
}
물론 이것을 테스트 하는 존재도 만들었습니다.
public class Magazine2Test {
public static void main(String[] args) {
Book2 obj = new Magazine2();
obj.doA();
}
}
이 코드를 실행하는 엔진의 해석은 다음과 같습니다.
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=2, Args_size=1
0: new #16; //class Magazine2
3: dup
4: invokespecial #18; //Method Magazine2."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #19; //Method Book2.doA:()V
12: return
LineNumberTable:
line 6: 0
line 8: 8
line 10: 12
LocalVariableTable:
Start Length Slot Name Signature
0 13 0 args [Ljava/lang/String;
8 5 1 obj LBook2;
}
컴파일러가 체크하는 로직을 보면 상당히 재밌습니다.
[loading java/lang/Object.class(java/lang:Object.class)]
[loading java/lang/String.class(java/lang:String.class)]
[checking Magazine2Test]
[loading ./Book2.java]
[parsing started ./Book2.java]
[parsing completed 1ms]
[loading ./Magazine2.java]
[parsing started ./Magazine2.java]
[parsing completed 1ms]
[wrote Magazine2Test.class]
[checking Book2]
[loading java/lang/System.class(java/lang:System.class)]
[loading java/io/PrintStream.class(java/io:PrintStream.class)]
[loading java/io/FilterOutputStream.class(java/io:FilterOutputStream.class)]
[loading java/io/OutputStream.class(java/io:OutputStream.class)]
[wrote ./Book2.class]
[checking Magazine2]
[wrote ./Magazine2.class]
컴파일러는 보는 바처럼 Book2클래스부터 메모리로 체크하기 시작합니다.
즉 변수의 타입에 나온 것을 보고 메모리로 올리는 겁니다.
클래스라는 것은 컴파일러가 사용하는 정보이기 때문입니다.
즉 Java가 overriding이라는 기법을 사용하는 것은 컴파일러가 보는 클래스와 실제 실행엔진이 실행하는 클래스의 객체와의 불일치를 가져오게 됩니다.
음..좀 더 길게 쓰고 싶었는데.. 우선 커피숖에서 원고쓰기는 너무 힘들어요...
댓글 없음:
댓글 쓰기