Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are generics said to be invariant when "? extends Klass" is allowed?

Tags:

java

generics

In Java, its said that:

String[] is subtype of Object[]

so arrays are said to be covariant. But for generics they say:

List<X> will not be subType of List<Y>.

and hence its invariant. But the question is, "are generics really invariant"?

For example, if I give:

List<? extends Exception>

this means that the list can take the subtype of Exception, say for example this is valid:

List<? extends Exception> k = new ArrayList<NumberFormatException>();

Then why Generics are said to be invariant?

like image 784
batman Avatar asked Jan 09 '23 02:01

batman


2 Answers

List<? extends Exception> k = new ArrayList<NumberFormatException>();

this means that the list can take the subtype of Exception

Not quite. You can assign to k a List -- or any of its subtype, as you have ArrayList -- in this case, of any subtype of Exception.

But you cannot add to k any subtype of Exception, or anything for that matter, because k is a List of some unknown subtype of Exception. For example,

k.add(new NumberFormatException());

would give an error.

Retrieval is also restricted to the known type:

NumberFormatException e1 = k.get(0); // error
Exception e2 = k.get(0); // ok, anything in k must be an Exception
NumberFormatException e3 = (NumberFormatException) k.get(0); // ok, but the usual downcast issues exist
like image 105
Miserable Variable Avatar answered Jan 26 '23 16:01

Miserable Variable


I think the simple answer to your question is a semantic one.
List<Object> is not a supertype for List<String>. Collection<String> is its supertype, while ArrayList<String> is one of its possible subtypes.

Putting it in another way :

 Object[] array = new String[2]; //is a valid declaration.
 List<Object> list = new ArrayList<String>(); //is not. 
like image 34
Angelo Alvisi Avatar answered Jan 26 '23 15:01

Angelo Alvisi