为什么可以转换泛型 class?

Why is it possible to cast generic class?

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);

    }
}

我想答案是这种转换是可能的,因为 Integer 可以作为参数 el 传递,在这种情况下转换是正确的。在 Integer 以外的所有其他类型的情况下,它将被非法转换。但是正如我在泛型中看到的那样,如果至少有一种类型可以给出正确的转换(Integer),那么编译器不会给出错误,而是警告,即使所有其他情况都无效。

在 Java 中,执​​行在编译时已知始终不正确或始终正确的显式转换是编译错误。从 List<Integer>List<Object> 的转换在编译时已知总是不正确的,因此不允许。从 List<Integer>List<T> 的转换在编译时并不知道总是不正确的——如果 TInteger 并且 T 是编译时未知。

对象是 class 整数的超 class。 List<Object> 不是 class List<Integer> 的超级 class ,但是如果你想 List<Object> 引用 List<Integer> 你可以使用小丑符号 (?)。

List<?> list1 = new List<Object>();
List<?> list2 = new List<Integer>();
list1 = list2;