Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Covariance and contravariance for wildcarded types

Can you please explain why it is possible to do:

import java.util.ArrayList;
import java.util.List;

public class Covariance {

    class A {
    }

    class B extends A {
    }

    class C extends A {
    }

    public void testSmth() throws Exception {
        List<? extends A> la = new ArrayList<A>();
        A a = la.get(0);
        // la.add(new B()); - doesn't compile

        List<? super B> lb = new ArrayList<A>();
        // lb.add(new A()); - doesn't compile
        lb.add(new B());
        Object object = lb.get(0);
    }

}

I don't understand, why it is not possible to add something to covariant list la, but it's still possible to add B to contravariant list lb - but not A to lb.

From my point of view, it should be possible to add everything extending A to List. I can see the only reason of not doing that because it is easy to add C to list of B, like

 List<B> lst = new ArrayList<B>();
 List<? extends A> lstB = lst;
 lstB.add(C); // this is valid for <? extends B> but list lst would contain instance of B.

Probably the same is true for contravariance, e.g

 List<B> lst = new ArrayList<B>;
 List<? super C> lstC = lst;
 lstC.add(new C());
 Object obj = lstC.get(0);

What I don't understand - why it is not possible to do

 B b = lstC.get(0);

It is obvious that on this stage super of C would be class B - Java doesn't allow multiple inheritance.

Also why it prohibits

 lstC.add(new B());

it's not clear for me.

like image 901
jdevelop Avatar asked Oct 11 '22 22:10

jdevelop


2 Answers

To understand what's going on with the super keyword, consider the following:

import java.util.ArrayList;
import java.util.List;

public class Covariance {

    class A {
    }

    class B extends A {
    }

    class C extends A {
    }

    class D extends C {}

    public void testSmth() throws Exception {
        List<? super D> ld = new ArrayList<C>();
    }

}

Hopefully this illustrates that ld can be a List of any super type of D, even one that be a subclass of A.

like image 184
MGwynne Avatar answered Oct 14 '22 01:10

MGwynne


consider

    List<? extends A> la = new ArrayList<C>();

it's a list of C. if we could add B to it, that would violate the list type.

like image 22
irreputable Avatar answered Oct 14 '22 03:10

irreputable