IntelliJ 显示的行为对我来说很清楚:
你有一个未经检查的演员表MyClass
。当执行此行时,这意味着new Integer(8)
不会立即Long
转换为擦除Number
(有效):N n =(N)(new Integer(8));
现在让我们看看输出语句:
System.out.println(new MyClass<Long>().n);
归结为String.valueOf(new MyClass<Long>().n)
->((Object)new MyClass<Long>().n).toString()
工作正常,因为 n 是通过访问的,Object
并且该toString()
方法是通过静态类型访问的Object
-> 不会Long
发生强制转换。new MyClass<Long>().n.toString()
将失败并出现异常,因为toString()
试图通过静态类型访问Long
。因此,发生 n 到 type 的强制转换Long
是不可能的(Integer
不能强制转换为Long
)。
执行第二条语句时也会发生同样的事情:
System.out.println(new MyClass<Long>().n.getClass());
尝试通过静态类型访问类型的getClass
方法(在 中声明Object
)。因此,发生类型转换的 n 会产生转换异常。Long
Long
Long
JShell 行为:
我试图重现 JShell - Java 9 early access Build 151 上第一个输出语句的异常:
jshell> class MyClass<N extends Number> {
...> N n = (N) (new Integer(8));
...> }
| Warning:
| unchecked cast
| required: N
| found: java.lang.Integer
| N n = (N) (new Integer(8));
| ^--------------^
| created class MyClass
jshell> System.out.println(new MyClass<Long>().n);
8
jshell> System.out.println(new MyClass<Long>().n.getClass());
| java.lang.ClassCastException thrown: java.base/java.lang.Integer cannot be cast to java.base/java.lang.Long
| at (#4:1)
但似乎 JShell 给出的结果与 IntelliJ 完全相同。System.out.println(new MyClass<Long>().n);
输出 8 - 也不例外。