2017-02-26 12 views
8

다른 답변을 작성할 때 investigating a stack trace discrepancy 동안 나는 이해하지 못하는 행동을 보았습니다.스택 추적의 신비한 라인

interface TestInterface <U> { 
    void test (U u); 
} 

static class Test <T extends Test<T>> implements TestInterface<T> { // line 11 
    @Override public void test (T t) { 
     throw new RuntimeException("My exception"); // line 13 
    } 
} 

static class TestA extends Test<TestA> { } 
static class TestB extends Test<TestB> { } 

public static void main (String[] args) throws Exception { 

    try { 
     Test a = new TestA(); 
     Test b = new TestB(); 
     a.test(b);   
    } catch (Exception x) { 
     x.printStackTrace(System.out); 
    } 

    try { 
     TestInterface a = new TestA(); 
     Test b = new TestB(); 
     a.test(b);   
    } catch (Exception x) { 
     x.printStackTrace(System.out); 
    } 

    try { 
     TestInterface a = new TestA(); 
     TestInterface b = new TestB(); 
     a.test(b);   
    } catch (Exception x) { 
     x.printStackTrace(System.out); 
    } 

} 

라인 (11)과 13 위의 코드에서 표시되어 있으며 run on ideone가 될 수 있습니다 (이 멀리 아래로 내가 범위를 좁힐 수 있습니다 같다)는 다음 테스트 프로그램을 고려하십시오. 이 프로그램의 출력은 다음과 같습니다

java.lang.RuntimeException: My exception 
    at Ideone$Test.test(Main.java:13) 
    at Ideone.main(Main.java:25) 
java.lang.RuntimeException: My exception 
    at Ideone$Test.test(Main.java:13) 
    at Ideone$Test.test(Main.java:11) 
    at Ideone.main(Main.java:33) 
java.lang.RuntimeException: My exception 
    at Ideone$Test.test(Main.java:13) 
    at Ideone$Test.test(Main.java:11) 
    at Ideone.main(Main.java:41) 

내 질문은 : 왜 두 번째와 세 번째 테스트 케이스의 스택 트레이스 라인 (11)은? 세 테스트 케이스의 차이점은 ab의 선언 된 유형입니다.

라인 (11) (클래스 선언 행)은하기 조건 하에서 만 존재한다 : Test이 인터페이스를 구현

  1. 경우와
  2. 예외는 인터페이스 방법에서 발생하는 경우와
  3. 인터페이스가 형식 매개 변수를 사용하는 경우
  4. 클래스 선언의 형식 매개 변수에 extends Test<T> (class Test<T>으로 선언 된 경우 줄 11은 포함되지 않음) 및
  5. Test 유형 대신 TestInterface 유형에서 메소드가 호출되는 경우. 그 주목

:

그것은 확실히 내 예외가 발생되고
  • (메시지 및 스택 추적).
  • 광산을 던지지 않으면 다른 예외가 발생하지 않습니다.
  • 필자는 Windows에서 Oracle JDK 1.7 및 1.8, Ideone에서 1.8을 사용하여이를 재현했습니다. 그러나 1.7에는 11 대신 2 행에 스택 추적 요소가 포함되어 있습니다 (두 배 이상입니다).

여기 무슨 일입니까? 그 라인은 스택 트레이스에서 어떻게 끝나고 두 오브젝트가 모두 Test으로 선언되면 나타나지 않는 이유는 무엇입니까? aComparable 선언하지만 Enum가 선언 될 때 존재하지 않는 경우 java.lang.Enum 라인 (55)이 존재

Here is the original program that prompted this

. 55 행은 JDK 소스에있는 Enum의 선언이고, 180 행은 명시 적으로 ClassCastException을 던집니다.

답변

13

당신은 bridge method의 효과를보고 있습니다! TestInterface 선언

test있어서 소거 test(Object)을 가지고 있지만 Test에서 선언 test 방법 소거 test(Test)있다. test(Object) 메소드 검색은 test(Test) 메소드를 찾지 못하기 때문에 실제로 의 바이트 코드에 Java가 별도의 test(Object)test(Test) 메소드를 넣습니다.

첫 번째 평가판은 예상대로 작동하는 test(Test) 메서드를 사용합니다. 다른 시도는 test(Object) 메서드를 사용합니다.이 메서드는 test(Test) 메서드를 호출하는 합성 브리지 메서드입니다. 이 브리지 메소드에는 실제로 행 번호가 없으므로 상당히 임의의 행 번호 11 인 스택 추적에 표시됩니다.