问题描述
我正在使用java 8.
I am using java 8.
我最近遇到过这个问题:
I recently came across this:
public class Test {
public static void main(String[] args) {
String ss = "" + (Test.<Integer>abc(2));
System.out.println(Test.<Integer>abc(2));
}
public static <T> T abc(T a) {
String s = "adsa";
return (T) s;
}
}
这不会抛出java.lang.ClassCastException。这是为什么?
This does not throw a java.lang.ClassCastException. Why is that?
我一直认为 +
和 System.out.println
调用 toString
。但是当我尝试这样做时,它会按预期抛出异常。
I always thought +
and System.out.println
calls toString
. But when I try to do that it throws an Exception as expected.
String sss = (Test.<Integer>abc(2)).toString();
推荐答案
它不会抛出 ClassCastException
因为从编译的代码中剥离了所有泛型类型信息(一个名为)。基本上,任何类型参数都被 Object
替换。这就是第一个版本有效的原因。这也是代码编译的原因。如果您要求编译器使用 -Xlint:unchecked
标志警告未经检查或不安全的操作,您将收到有关 return 的声明abc()
。
It doesn't throw a ClassCastException
because all generic type information is stripped from the compiled code (a process called type erasure). Basically, any type parameter is replaced by Object
. That's why the first version works. It's also why the code compiles at all. If you ask the compiler to warn about unchecked or unsafe operations with the -Xlint:unchecked
flag, you'll get a warning about an unchecked cast in the return
statement of abc()
.
使用此声明:
String sss = (Test.<Integer>abc(2)).toString();
这个故事有点不同。虽然类型参数 T
被 Object
替换,但调用代码被转换为显式转换结果的字节代码整数
。就好像代码是用带有签名 static Object abc(Object)
的方法编写的,并且语句写成:
the story is a bit different. While the type parameter T
is replaced by Object
, the calling code gets translated into byte code that explicitly casts the result to Integer
. It is as if the code were written with a method with signature static Object abc(Object)
and the statement were written:
String sss = ((Integer) Test.abc(Integer.valueOf(2))).toString();
也就是说,不仅中的演员表abc()
由于类型擦除而消失,编译器在调用代码中插入一个新的强制转换。此转换在运行时生成 ClassCastException
,因为从 abc()
返回的对象是字符串
,而不是整数
。
That is, not only does the cast inside abc()
go away due to type erasure, a new cast is inserted by the compiler in the calling code. This cast generates a ClassCastException
at run time because the object returned from abc()
is a String
, not an Integer
.
注意语句
String ss = "" + (Test.<Integer>abc(2));
不需要强制转换,因为编译器只是提供返回的对象abc()
进入对象的字符串连接操作。 (有关如何完成此操作的详细信息因Java编译器而异,但它是对 StringBuilder
append方法的调用,或者从Java 9开始,调用方法由 StringConcatFactory
创建。)这里的细节无关紧要;重点是编译器足够聪明,可以识别不需要强制转换。
doesn't require a cast because the compiler simply feeds the object returned by abc()
into a string concatenation operation for objects. (The details of how this is done varies with the Java compiler, but it is either a call to a StringBuilder
append method or, as of Java 9, a call to a method created by StringConcatFactory
.) The details here don't matter; the point is that the compiler is smart enough to recognize that no cast is needed.
这篇关于Java泛型投射奇怪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!