2011년 1월 7일 금요일

오버라이딩의 실체

동영상 강의 제작하다가 문득 내용이 괜찮을 듯 해서 블로그로 다시 정리합니다. 


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이라는 기법을 사용하는 것은 컴파일러가 보는 클래스와 실제 실행엔진이 실행하는 클래스의 객체와의 불일치를 가져오게 됩니다. 

음..좀 더 길게 쓰고 싶었는데.. 우선 커피숖에서 원고쓰기는 너무 힘들어요... 



댓글 없음:

댓글 쓰기