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 会产生转换异常。LongLongLong
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 - 也不例外。