Java 泛型是不变的,所以不可能进行这样的转换:
List<Object> li = (List<Object>)new ArrayList<Integer>();
但是在第 4 行的以下代码中,我可以从 List<Integer>
转换为 List<T>
,其中T
可以是任何类型的。为什么允许这种类型的演员表?
我知道它会生成有关未经检查的转换的警告,但关键是这种转换可以在参数化方法中实现,但在普通代码中则不然。请记住,泛型是不变的,为什么允许它?在普通代码中,当有List<Integer>
时,我只能将其转换为没有意义的List<Integer>
,其他强制转换是非法的。那么,允许像第 4 行这样的演员有什么意义呢?
我知道泛型类型在编译时被删除并以 List xlist = (List)list
结尾,但在删除这些类型之前,很明显不应该允许这种强制转换,除非它仅在有人将 Integer 传递为el
的情况下被接受,这没有多大意义。
class Test {
public static <T> void t(List<Integer> list, T el) {
List<T> xlist = (List<T>)list; //OK
xlist.add(el);
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
t(list, "a");
t(list, "b");
//prints [a, b] even if List type is Integer
System.out.println(list);
}
}
在 Java 中,执行在编译时已知始终不正确或始终正确的显式强制转换是一个编译错误。从 List<Integer>
到 List<Object>
的强制转换在编译时总是不正确的,因此不允许这样做。从 List<Integer>
到 List<T>
的强制转换在编译时并不总是不正确的——如果T
Integer
,那么它是正确的,而T
在编译时是未知的。
我想答案是这个强制转换之所以可能,只是因为它可以作为参数el
传递Integer
在这种情况下,该转换是正确的。在除整数以外的所有其他情况下,它将是非法转换的。但是正如我在泛型中看到的那样,如果至少有一个类型会给出正确的强制转换(Integer
),那么编译器不会给出错误,而是警告,即使所有其他情况都是无效的。
Object 是类 Integer 的超类。 List<Object>
不是类List<Integer>
的超类,但此外,如果你想让List<Object>
引用一个List<Integer>
你可以使用小丑符号(?)。
List<?> list1 = new List<Object>();
List<?> list2 = new List<Integer>();
list1 = list2;