以下是我写过的第一个Java泛型:
public class MyClass {
public static <T> T castToAnotherType(Object param) {
T ret = null;
try {
ret = (T) param;
} catch (ClassCastException e) {
System.out.print("Exception inside castToAnotherType()");
}
return ret;
}
public static void main(String[] args) {
try {
String obj = MyClass.castToAnotherType(new Object());
} catch (ClassCastException e) {
System.out.print("Exception outside castToAnotherType()");
}
}
}
结果是“castToAnotherType()之外的异常”。为什么在泛型方法中不会发生异常?
答案 0 :(得分:15)
T
被有效删除。见here:
泛型被引入Java语言以提供更紧密的类型 在编译时检查并支持通用编程。至 实现泛型,Java编译器将类型擦除应用于:
- 将泛型类型中的所有类型参数替换为其边界或 对象,如果类型参数是无界的。生成的字节码, 因此,只包含普通的类,接口和方法。
- 必要时插入类型转换以保持类型安全。生成 用于保留扩展泛型类型中多态性的桥接方法。
- 类型擦除确保不会为参数化创建新类 类型;因此,泛型不会产生运行时开销。
因此,castToAnotherType
将T
删除为public static Object castToAnotherType(Object param) {
Object ret = null;
try {
ret = (Object) param;
} catch (ClassCastException e) {
System.out.print("Exception inside castToAnotherType()");
}
return ret;
}
。以下内容:
ClassCastException
这显然不会产生任何main(...)
。
public static void main(String[] args) {
try {
String obj = (String) MyClass.castToAnotherType(new Object());
} catch (ClassCastException e) {
System.out.print("Exception outside castToAnotherType()");
}
}
是一个不同的故事,它产生于以下内容:
ClassCastException
在尝试将Object
投射到String
时产生{{1}}。
答案 1 :(得分:4)
好吧,由于编译器会删除泛型类型参数,因此方法内部的转换基本上等同于:
Object ret = null;
try {
ret = (Object) param;
}
...
这不是问题,无论你传递给你的方法是什么(因为任何Object都可以转换为Object)。
但是,当您尝试将该Object分配给字符串时,在main方法中会出现ClassCastException
,因为Object
无法转换为String
。
答案 2 :(得分:3)
所有泛型类型都在已编译的代码中被删除。就编译代码而言,castToAnotherType
只返回Object
。但是,您的main
方法尝试将其分配给String
,而不是String
,因此生成ClassCastException
。
答案 3 :(得分:3)
这是因为通用类型擦除,
T ret = null;
try {
ret = (T) param;
...
由编译器翻译成
Object ret = null;
try {
ret = (T) param;
...