我是Java新手。据我所知,It's basically the way that generics are implemented in Java via compiler trickery。
public Object doSomething(Object obj) {....}
public <T> T doSomething(T t) {....}
根据类型擦除,上述两种方法在运行时是相同的。唯一不同的是我们使用这种方法的方式,当我们使用泛型方法时,编译器会自动添加类型转换。
Foo newFoo = (Foo) my.doSomething(foo);
同样,当我们在方法中使用泛型数组时,如下所示:
public void <T> T[] f(T[] args){
return args;
}
public void <T> Object[] f(Object[] args){
return args;
}
我认为由于类型擦除,上述两种方法在运行时是相同的。
Integer[] a = {1, 2};
Integer[] b = test.f(a);
当我使用这个方法时,我认为泛型方法会抛出一个CaseException。
当我们将a
传递给test.f(a)
时,JVM会将Integer[]
投射到Object[]
。
当我们从这个方法得到结果时,JVM也会将Object[]
强制转换为Integer[]
,这个强制转换将抛出一个CaseException。因为java中的数组是支持协变而不是逆变。
因此,上面的代码在编译和运行时都有效。我的理解肯定有些不对劲。但我找不到。谁能帮我?谢谢!
答案 0 :(得分:1)
T
代表具体类型,不能代替Object
。它带有实际类型。因此,当您将Integer[]
传递给该方法时,它将返回Integer[]
并且它正常工作 - 编译器知道类型。
使用第二种方法,当Object[]
获得所期望的行为时,您可以将Integer[]
传递给Object[]
,但不能反过来,而且会出现编译错误。< / p>
工作示例:
public static <T> T[] f1(T[] args){
return args; //That one works because we return T[]
}
public static <T> T[] f2(Object[] args){
return (T[])args; //That one also works because we return T[]
}
下一个不起作用,因为我们返回的Object []可能是T类型但可能是另一种类型 - 它不会编译
public static Object[] f2(Object[] args){
return args; //Object[] is not T[]
}