Ковариантность и контравариантность для подстановочных знаков - PullRequest
5 голосов
/ 26 мая 2011

Не могли бы вы объяснить, почему это можно сделать:

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);
    }

}

Я не понимаю, почему невозможно добавить что-либо в ковариантный список la, но все еще можно добавить B вконтрвариантный список lb - но не A к lb.

С моей точки зрения, должно быть возможно добавить все, что расширяет A в List.Я вижу единственную причину не делать этого, потому что легко добавить C в список B, например,

 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.

Возможно, то же самое верно для контравариантности, например,

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

Чего я не понимаю - почему это невозможно сделать

 B b = lstC.get(0);

Очевидно, что на этом этапе супер C будет классом B - Java не допускает множественное наследование.

Также почему он запрещает

 lstC.add(new B());

, мне не понятно.

Ответы [ 2 ]

2 голосов
/ 27 мая 2011

Чтобы понять, что происходит с ключевым словом super, рассмотрите следующее:

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>();
    }

}

Надеюсь, это показывает, что ld может быть списком любого супертипа D, даже одного, который является подклассом A.

2 голосов
/ 26 мая 2011

1001 * рассмотреть *

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

это список C. Если бы мы могли добавить к нему B, это нарушило бы тип списка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...