2010-01-05 3 views
3

다음 코드의 경우 왜 A, B를 인쇄합니까? B, B를 인쇄 할 것으로 예상됩니다. 또한 JVM에서 수행하는 메서드 호출이 동적으로 또는 정적으로 평가됩니까?Java 메소드 호출 과부하 논리

public class Main { 
    class A { 

    } 

    class B extends A { 

    } 

    public void call(A a) { 
     System.out.println("I'm A"); 
    } 

    public void call(B a) { 
     System.out.println("I'm B"); 
    } 


    public static void main(String[] args) { 

     Main m = new Main(); 
     m.runTest(); 
    } 

    void runTest() { 
     A a = new B(); 
     B b = new B(); 

     call(a); 
     call(b); 
    } 

} 

답변

14

오버로딩 컴파일러에 의해 정적으로 결정된다. 을 무시하면 실행 시간에 완료되지만 여기에는 요소가 아닙니다.

정적 유형 a은 A이므로 첫 번째 메서드 호출은 call(A a)으로 확인됩니다.

+0

감사합니다. 그렇다면 동적으로 평가되는 것은 무엇입니까? –

+0

@Maxim Veksler : 재정의 (override) - 이것은 컴파일 타임 타입이 아닌 대상 객체의 * 실제 * 타입에 의해 결정됩니다. –

+0

존 감사합니다. –

3

개체가 그 시점에 A 유형으로 알려져 있으므로 A 인수가있는 메서드가 호출됩니다. 그래서 예, 결정했습니다 정적으로.

모호성을 피하기 위해서입니다. BA입니다. 그러나 두 가지 방법을 동시에 호출 할 수는 없습니다.

1

BA의 하위 클래스입니다. B을 설치했지만 A 유형의 변수에 할당하면 B의 모든 내용이 '손실'되므로 call(a)call(A, a)으로 발송되고 'A'가 인쇄됩니다.

+0

그건 약간 잘못된 것입니다. 'a'라는 객체는 여전히 "B의 모든 특성"을 보유하고 있습니다 - 예를 들어'a.getClass(). getSimpleName() '을 호출하면 "B"가 반환됩니다. Jon이 지적한 바와 같이, 오버로드는 컴파일 타임에 ** 참조 ** 유형에 따라 결정됩니다. 컴파일러는이 문맥에서'a'가 실제로'B'의 인스턴스라는 것을 "알지"못하기 때문에'call (A a)'메소드에 대한 호출을 컴파일합니다. 그러나'a'는'B'의 인스턴스입니다. –