java - 为什么可以转换泛型类?

标签 java generics casting invariance

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> 的 Actor 阵容至 List<Object>在编译时已知总是不正确的,因此它是不允许的。来自 List<Integer> 的 Actor 阵容至 List<T>在编译时不知道它总是不正确的——如果 T 就是正确的是Integer , 和 T在编译时未知。

关于java - 为什么可以转换泛型类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37331920/

相关文章:

Java 资源文件夹名称与其他名称

c# - 父/子泛型关系

c# - 定义此通用接口(interface)以便编译的最干净的方法是什么?

java - 为什么在静态泛型方法的返回类型之前需要类型参数

Java 和动态类型

typescript - 将 Object<T> 转换为 Object<A>,其中 A 包含在 T 中

java - 在java 8中将拖动的组件添加到JPanel

java - 由于堆 OOM,kafka 代理无法处理请求

JavaCV-OpenCV错误

casting - typescript :在评论中设置变量类型