数组如何“记住”他们在Java中的类型? [英] How do arrays "remember" their types in Java?

查看:99
本文介绍了数组如何“记住”他们在Java中的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下代码:

  class AA {} 

class BB extends AA {}

public class Testing {

public static void main(String [] args){
BB [] arr = new BB [10];
AA [] arr2 = arr;

BB b = new BB();
AA a =新AA();
arr2 [0] = a; // ArrayStoreException在运行时
arr2 [1] = b;

列表< BB> listBB = new ArrayList<>();
列表listAA = listBB;
listAA.add(hello world.txt);


$ b code
$ b在上面的例子中,当我尝试 arr2 [0] = a 时, ArrayStoreException 。这意味着该数组会记住它必须接受的类型。但 List 不记得它们。它只是编译并运行良好。当我检索对象 BB 时,将引发 ClassCastException



所以问题是:
$ b $ ol
  • 数组是如何记住它的类型的(我知道它叫做reification)。这是怎么发生的?


  • 为什么在编译时不能检测 ArrayStoreException ,即当我执行 arr2 [0] = a 时,它可能会导致编译器错误,而不是在运行时检测它。

  • / ol>

    谢谢。

    解决方案


    1. 与泛型不同,数组的类型信息存储在运行时。从一开始它就是Java的一部分。在运行时,可以将 AA [] BB [] 区分开来,因为JVM知道它们的类型。 / b>


    2. 一个 ArrayList (以及其他的Collections框架)使用泛型, 。在运行时,泛型类型参数不可用,所以 ArrayList< BB> ArrayList< AA> ;它们都是JVM的 ArrayList s。

    3. 编译器只知道 arr2 是一个 AA [] 。如果你有一个 AA [] ,编译器只能假定它可以存储 AA 。编译器不会检测到类型安全问题,因为您将 AA 放置在真正的 BB [] 中,因为它只能看到 AA [] 参考。与泛型不同,Java数组是协变的,因为 BB [] AA [] ,因为 BB AA 。但是这引入了你刚刚演示的可能性 - 一个 ArrayStoreException ,因为 arr2 引用的对象实际上是一个 BB [] ,它不会处理 AA 作为元素。



    Consider the following code:

    class AA { }
    
    class BB extends AA { }
    
    public class Testing {
    
        public static void main(String[] args) {
            BB[] arr = new BB[10];
            AA[] arr2 = arr;
    
            BB b = new BB();
            AA a = new AA();
            arr2[0] = a; // ArrayStoreException at runtime
            arr2[1] = b;
    
            List<BB> listBB = new ArrayList<>();
            List listAA = listBB;
            listAA.add("hello world.txt");
    
        }
    }
    

    In the above example, I get the ArrayStoreException when I try arr2[0] = a. That means the array remembers what type it must accept. But the List does not remember them. It simply compiles and runs fine. The ClassCastException will be thrown when I retrieve the object BB.

    So the questions are:

    1. How an array remembers its type (I know it's called "reification"). How this happens exactly?

    2. And why only arrays are bestowed with this power but not ArrayList although it uses an array under its hood.

    3. Why can't ArrayStoreException be detected at compile time, i.e when I do arr2[0] = a, it could cause a compiler error, instead of detecting it at runtime.

    Thanks.

    解决方案

    1. The type information for arrays, unlike for generics, is stored at runtime. This has been part of Java since the beginning of it. At runtime, a AA[] can be distinguished from a BB[], because the JVM knows their types.

    2. An ArrayList (and the rest of the Collections framework) uses generics, which is subject to type erasure. At runtime, the generic type parameter is not available, so an ArrayList<BB> is indistinguishable from an ArrayList<AA>; they are both just ArrayLists to the JVM.

    3. The compiler only knows that arr2 is a AA[]. If you have a AA[], the compiler can only assume that it can store an AA. The compiler will not detect a type safety issue in that you are placing an AA in what's really a BB[] there, because it only sees the AA[] reference. Unlike generics, Java arrays are covariant, in that a BB[] is an AA[] because a BB is an AA. But that introduces the possibility of what you just demonstrated - an ArrayStoreException, because the object referred to by arr2 is really a BB[], which will not handle an AA as an element.

    这篇关于数组如何“记住”他们在Java中的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆