Search code examples
javagenericswildcardbounded-wildcard

add (List<? extends Z>) where Z is an interface . Class B extends A implements Z why cant we call add() with a List<A>


 Interface Z{}

Consider a simple interface Z as declared above.

Class A{}

A simple class A as declared above.

 Class B extends A implements Z{}

Class B extends class A and implements interface Z

class Test{

static void add(List<? super Z>){}

public static void main(String[]  args){
List<A> aaa= new ArrayList<>();
add(aaa);  //Gives error here
} 
}

The add method in above test class has a parameter List so as far as i know i can call it with alist of type Z or with a list of type super class of implementation class of Z.

class B is an implementation of Z but is also a child of A so class A satisfies the condition above .It is a super class of (class B) implementation class of Z(class B).

So when i call add() with an ArrayList why does it give an error.


Solution

  • Imagine this is the method body of add. This compiles fine:

    static void add(List<? super Z> list){
      list.add(new Z() {});  // Fine.
    }
    

    Also, this compiles fine.

    List<A> aaa= new ArrayList<>();
    // ... Something.
    A a = aaa.get(0);
    

    Now, what if the ... Something is:

    add(aaa);  // Compiler error!
    

    What would happen if that compiler error didn't happen? A ClassCastException on the A a = aaa.get(0); line, because it's an instance of some subclass of Z that's not A.

    Try it, by invoking add((List) aaa).

    This is why the compiler stops you doing it. List<? super Z> is a list to which it's safe to add instances of Z, or any subclass. List<A> is a list to which it's safe to add instances of A, or any subclass, or null; and anything you retrieve from the list will be an A, a subclass, or null. Some instances of Z aren't instances of A.