最后,我尝试了一些仿制药。我想出了这段代码:
public class Test {
static <T> void f(T x) {
x = (T) (Integer) 1234;
System.out.println(x);
}
public static void main(String[] args) {
f("a");
f(1);
f('a');
f(1.5);
f(new LinkedList<String>());
f(new HashMap<String, String>());
}
}
我跑了这个并得到了这个输出:
1234
1234
1234
1234
1234
1234
没有例外!怎么可能?
答案 0 :(得分:37)
这是因为type erasure(已经写了很多关于此的内容,只是google这个术语)。在将f
编译为字节代码后,该方法可能如下所示:
static void f(Object x) {
x = (Object) (Integer) 1234;
System.out.println(x);
}
因此System.out.println
只会调用对象toString
上的x
方法 - 在您的情况下,它是Integer.toString()
。
答案 1 :(得分:4)
因为类型擦除。来自Oracle's documentation:
泛型被引入Java语言以提供更紧密的类型 在编译时检查并支持通用编程。至 实现泛型,Java编译器将类型擦除应用于:
将泛型类型中的所有类型参数替换为其边界或 对象,如果类型参数是无界的。生成的字节码, 因此,只包含普通的类,接口和方法。
如有必要,插入类型转换以保护类型安全。
- 生成桥接方法以保留扩展泛型类型中的多态性。
类型擦除确保不会为参数化创建新类 类型;因此,泛型不会产生运行时开销。