difference between creation unbounded and bounded wild card type array?

匿名 (未验证) 提交于 2019-12-03 03:05:02

问题:

Why is this code valid

ArrayList<?>[] arr = new ArrayList<?>[2];

but the following two are not?

ArrayList<? extends Object>[] arr = new ArrayList<? extends Object>[2]; ArrayList<? super Object>[] arr = new ArrayList<? super Object>[2];

The two last rows generate the compile error;

error: generic array creation.

Please clarify difference.

update

On the other hand ArrayList<?>[] arr = new ArrayList<?>[2]; compiles good but

ArrayList<?> arr = new ArrayList<?>();

not.

回答1:

There are a few issues going on here, lets look at each in turn:

  1. A type bound (ie extends Object) can only be declared when declaring a type, it cannot be used when instantiating an object.

    for example

    ArrayList<? extends Object> ab = new ArrayList<? extends Object>(); // error ArrayList<? extends Object> ac = new ArrayList<String>(); // okay

  2. Arrays do not support type parameters, for example:

    List<Integer>[] arrayOfLists = new List<Integer>[2]; // compile time error List<Integer> list = new List<Integer>(); // okay

    Oracle documents the reasons for this limitation here.

  3. <?> can be used when declaring a type parameter, and with arrays. It was added to help avoid 'unchecked exception' errors when mixing Java code that does and does not use generics. It means 'unknown generic type'. More detail on unbounded wild cards here.

    ArrayList<?>[] arr = new ArrayList<?>[2];

    is valid for the reasons outlined above. However it is of very limited use because only null can be assigned to types declared as <?>.

    arr[0] = null; // compiles

    arr[1] = new Object(); // compile time error

    Oracle provides the following Guide on using wildcards which will help to understand when to use this wild cards.

  4. <?> cannot be used to instantiate an object. For example

    ArrayList<?> arr = new ArrayList<?>(); // does not compile

    ArrayList<?> arr2 = new ArrayList<>(); // but this does

    ArrayList<?> arr3 = new ArrayList<String>(); // and so does this

    However one still has the problem that using <?> only accepts null.

    arr3.add( " " ); // does not compile even though it was instantiated with String

    arr3.add( null ); // compiles just fine



回答2:

You have to first understand why creating an array of a parameterized type is not allowed. It's because arrays check at runtime that elements inserted are instances of the component type (a la instanceof). It is not possible to check instanceof a parameterized type, because an object does not have a sense of the type parameter with which it was created. instanceof ArrayList<Integer> is illegal in Java, as is something like instanceof ArrayList<? extends Number>, but instanceof ArrayList<?> is allowed in Java because it needs no information about the type parameter of the object. (By the way instanceof ArrayList<? extends Object> and instanceof ArrayList<? super Object> are also illegal.)

Conceptually, ArrayList<? extends Object> is almost completely identical to ArrayList<?> (there are minor differences but not relevant), but for consistency of the grammar, new ArrayList<? extends X>[...] is not allowed for any X.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!