返回泛型变长参数数组为何仅二级调用时抛出ClassCastException?
为什么泛型变长参数方法直接调用不抛ClassCastException,间接调用却抛出?
先看你的代码:
public class Main { private static class A<T>{ } static <T> T[] fun(T... arr){ return arr; } static <T> T[] fun2(T a, T b){ return fun(a, b); } public static void main(String[] args) { String[] z = fun("1", "2"); // 无异常 String[] s = fun2("1","2"); // 抛出ClassCastException } }
直接调用fun("1", "2")不抛异常的原因
Java的变长参数语法T... arr在编译阶段会被转换成数组参数T[] arr。当你直接在main里调用fun("1", "2")时,编译器能通过上下文推断出泛型参数T是String,所以它会在调用点创建一个String[]数组,把"1"和"2"放进去传递给fun。fun返回的就是这个String[],和你赋值的String[] z类型完全匹配,自然不会抛出类型转换异常。
调用fun2("1","2")抛出异常的原因
fun2是一个泛型方法,Java的类型擦除机制会把它的泛型参数T在编译后擦除为Object。当fun2内部调用fun(a, b)时,编译器此时无法确定T的具体类型(因为fun2本身的泛型信息已经被擦除),所以会创建一个Object[]数组传递给fun,fun返回的就是这个Object[]。
当fun2把这个Object[]返回给main方法时,main里试图将其赋值给String[] s,此时JVM会做运行时类型检查:发现实际返回的是Object[],而不是String[],所以直接抛出ClassCastException。这就是《Effective Java》里提到的堆污染(Heap Pollution)——泛型类型的变量引用了实际类型不匹配的对象。
简单说,直接调用时编译器帮你生成了对应类型的数组,间接调用时因为类型擦除,生成的是Object[],后续强转失败。
内容的提问来源于stack exchange,提问作者Seema Sharma
相关产品推荐
相关产品推荐

