Java中的泛型和子类型问题

参见英文答案 >
Why are arrays covariant but generics are invariant?                                    8个

首先,由于java具有严格类型系统,因此在编译时检查程序的类型是否正确,并且在执行之前将类加载到字节码验证器时检查程序的字节码.

虽然泛型的引入拓宽了Java类型系统的潜力,但由于java有子类型,在上面的例子中出现了很多问题:

 String [] a ={"Hello"};
        Object [] b= a;
        b[0]=  false;
        String s=a[0];

        System.out.println(s);

在上面的例子中,我们使用String类是Object的子类.
我的问题是编译器不会对上述程序产生任何警告的原因是什么.当我尝试运行它时(当然)抛出异常.
还有上述程序在java实现中可能遇到的问题/后果(我的意思是有任何明显的问题吗?).

最佳答案 Java中的数组是协变的,即. String []可以传递给期望Object []的东西.这就是为什么编译器不会阻止你将布尔值粘贴到String数组中的原因.

为了提供协方差但也提供运行时保护,Java工程师设计了数组,以便在编译时添加标记,从而使用其类型标记数组.即使我们可以在编译时添加布尔值,String []上的类型也阻止我们在运行时添加布尔值 – 这就是触发运行代码时可能遇到的ArrayStoreException的原因.

这是Java中的协变数组和捕获向数组添加错误内容的步骤之间的权衡.这种折衷是为什么某些语言,如Scala,选择不具有协变数组.

可以创建通用数组,但不是直截了当的,并且有一些类型的危险,因此这些方法适用于特定的用例–Josh Bloch的Effective Java讨论了这些.

因为你可以在编译时捕获问题,所以在数组上使用泛型列表可能会更好.

点赞