【发布时间】:2017-07-16 19:27:10
【问题描述】:
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);
}
}
上面的sn-p中标记了第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 行?三个测试用例的区别在于a和b的声明类型。
第 11 行(类声明行)仅在以下情况下出现:
- 如果
Test实现了一个接口,并且 - 如果从接口方法抛出异常,并且
- 如果接口采用类型参数,并且
- 如果类声明的类型参数包含
extends Test<T>(如果声明为class Test<T>,则不包括第11行),并且 - 如果在
TestInterface类型而不是Test类型上调用该方法。
注意:
- 肯定是我的异常被抛出(消息和堆栈跟踪)。
- 如果我不抛出我的,则不会抛出其他异常。
- 我已经在 Oracle JDK 1.7 和 Windows 上的 1.8 和 Ideone 上的 1.8 上复制了这个。但是,1.7 在第 1 行而不是第 11 行包含堆栈跟踪元素(这很奇怪)。
这里发生了什么?该行如何在堆栈跟踪中结束?如果两个对象都声明为Test,为什么它不会出现?
Here is the original program that prompted this,如果a 被声明为Comparable,则java.lang.Enum 的第55 行存在,但在它被声明为Enum 时不存在。第55行是JDK源码中Enum的声明,第180行是显式抛出的ClassCastException。
【问题讨论】:
标签: java generics exception language-lawyer stack-trace