Während investigating a stack trace discrepancy beim Verfassen einer anderen Antwort, stieß ich auf ein Verhalten, das ich nicht verstehe. Betrachten Sie das folgende Testprogramm (das ist so weit unten wie ich es verengen könnte):Mysteriöse Linie im Stapel verfolgen
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);
}
}
Linien 11 und 13 sind in dem obigen Schnipsel markiert und es kann run on ideone sein. Die Ausgabe dieses Programms ist:
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)
Meine Frage ist: Warum ist Linie 11 in der Stack-Trace für den zweiten und dritten Testfälle? Der Unterschied zwischen den drei Testfällen sind die deklarierten Typen a
und b
.
Zeile 11 (die Klassendeklaration Linie) ist nur vorhanden, unter den folgenden Bedingungen:
- Wenn
Test
eine Schnittstelle implementiert, und - Wenn die Ausnahme von der Schnittstellenmethode geworfen wird, und
- Wenn die Schnittstelle einen Typparameter verwendet und
- Wenn der Typparameter der Klassendeklaration
extends Test<T>
enthält (Zeile 11 ist nicht enthalten, wenn sie alsclass Test<T>
deklariert ist) und - Wenn die Methode über den Typ
TestInterface
statt über den TypTest
aufgerufen wird.
dass in Anbetracht:
- Es ist auf jeden Fall meine Ausnahme (Meldung und Stack-Trace) geworfen.
- Keine anderen Ausnahmen werden geworfen, wenn ich meine nicht werfe.
- Ich habe dies mit dem Oracle JDK 1.7 und 1.8 unter Windows und 1.8 auf Ideone reproduziert. 1.7 enthält jedoch ein Stack-Trace-Element in Zeile 1 statt in 11 (was doppelt seltsam ist).
Was passiert hier? Wie kommt es, dass diese Zeile im Stack-Trace endet und warum erscheint sie nicht, wenn beide Objekte als Test
deklariert sind?
Here is the original program that prompted this, wo die Leitung 55 von java.lang.Enum
vorhanden ist, wenn a
als Comparable
deklariert, aber nicht vorhanden, wenn es als Enum
deklariert wird. Zeile 55 ist die Deklaration von Enum
in der JDK-Quelle, Zeile 180 ist eine explizit geworfene ClassCastException
.