它不会抛出,
ClassCastException因为所有通用类型信息都已从编译后的代码中剥离(此过程称为类型擦除)。基本上,任何类型参数都由代替
Object。这就是第一个版本起作用的原因。这也是代码完全编译的原因。如果您要求编译器通过
-Xlint:unchecked标记警告未经检查的操作或不安全的操作,则会在的
return语句中收到有关未经检查的强制转换的警告
abc()。
带有以下语句:
String sss = (Test.<Integer>abc(2)).toString();
故事有点不同。当type参数
T替换为时
Object,调用代码将转换为字节代码,该字节代码将结果显式转换为
Integer。就像代码是使用带有签名的方法编写的,
staticObject abc(Object)并且语句是这样编写的:
String sss = ((Integer) Test.abc(Integer.valueOf(2))).toString();
也就是说,内部
abc()类型转换不仅会由于类型擦除而消失,而且编译器还会在调用代码中插入新的类型转换。该强制类型转换
ClassCastException在运行时生成a
,因为从返回的对象
abc()是
String,而不是
Integer。
注意声明
String ss = "" + (Test.<Integer>abc(2));
不需要强制转换,因为编译器只是将返回的对象提供给对象
abc()的字符串连接操作。(有关此操作的详细信息随Java编译器的不同而不同,但这是对
StringBuilderappend方法的调用,或者,从Java
9开始,是对
StringConcatFactory。创建的方法的调用。)这里的细节无关紧要;关键是编译器足够聪明,可以识别出不需要强制转换。



