Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

difference between creation unbounded and bounded wild card type array?

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.

like image 425
gstackoverflow Avatar asked Oct 01 '14 10:10

gstackoverflow


People also ask

What is the difference between bounded and unbounded wildcards in Java generics?

both bounded and unbounded wildcards provide a lot of flexibility on API design especially because Generics is not covariant and List<String> can not be used in place of List<Object>. Bounded wildcards allow you to write methods that can operate on Collection of Type as well as Collection of Type subclasses.

What is the difference between a wildcard bound and a type parameter bound?

What is the difference between a wildcard bound and a type parameter bound? A wildcard can have only one bound, while a type parameter can have several bounds. A wildcard can have a lower or an upper bound, while there is no such thing as a lower bound for a type parameter.

What is unbounded wildcard?

The unbounded wildcard type is specified using the wildcard character (?), for example, List<?>. This is called a list of unknown type. There are two scenarios where an unbounded wildcard is a useful approach: If you are writing a method that can be implemented using functionality provided in the Object class.

What is an unbounded generic type?

An unbound generic type is not itself a type, and cannot be used as the type of a variable, argument or return value, or as a base type. The only construct in which an unbound generic type can be referenced is the typeof expression (§11.7. 16).


2 Answers

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

like image 67
Chris K Avatar answered Oct 22 '22 02:10

Chris K


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.

like image 24
newacct Avatar answered Oct 22 '22 01:10

newacct