<? super E> and <? extends E> for List


Answers

The type definition List<? extends A> is not usable for a mutable List - the explanation given in Java generics Java Generics Pdf is

The add() method takes arguments of type E, the element type of the collection. When the actual type parameter is ?, it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don’t know what type that is, we cannot pass anything in.

However, when the typedef is List<? super A> then the type parameter ? is implicitly typed.

Question

Having the following simple class structure:

class A {
}

class B extends A {
}

class C extends B {
}

I'm creating an ArrayList to keep objects of the earlier created classes:

List<? extends A> list1 = new ArrayList<A>();
List<? extends B> list2 = new ArrayList<B>();
List<? extends C> list3 = new ArrayList<C>();

List<? super A> list4 = new ArrayList<A>();
List<? super B> list5 = new ArrayList<B>();
List<? super C> list6 = new ArrayList<C>();

To each of those lists I'm trying to add 1 object of each earlier created class: A,B,C. The only possible combination is:

  • adding object of class A,B,C to list4

  • adding object of class B and C to list5

  • adding object of class C to list list6. The rest of the tries gives compiler errors, such us:

The method add(capture#1-of ? extends A) in the type List is not applicable for the arguments (A)

Why can't I add any object of class A,B,C to list1/2/3? Why e.g. list4 accepts objects of classes A,B,C if they are supposed to be a super class of class A, as the list4 is defined?




What is meaning of List return type of method in java

For this generic method the return type is determined by the argument type. The argument can be List<Number> and List of subtypes of Number. Eg if you call process with this arg

List<Integer> list = ...
process(list)

the return type will be List<? super Integer>. Generic type with ? super can be assigned only to generic type with ? super

List<Integer> input = null;
List<? super Integer> output = process(input);

it cannot be List<Number> or List<Object> because they allow writing subclasses of generic parameter. Eg List<Number> list allows list.add(1L);

Correct answer is G.




It depends which way on the inheritance hierarchy it allows. Assume you have a class "Child" which inherits from "Parent" which inherits from "Grandparent".

<T extends Parent> accepts either Parent or Child while <T super Parent> accepts either Parent or Grandparent.







You shouldn't need to use the wildcard capture syntax in your case, simply declaring

List<MyType> listOfMytype;

should be enough. If you want to know exactly why, the Java Generics Tutorial has more than you would ever want to know about the esoteric craziness of Java Generics. Page 20 addresses your specific case.

As for why add with the wildcard capture does not work, it is because the compiler can't determine exactly what subclass of MyType the list will be in every case, so the compiler emits an error.





Tags