<? супер E> и <? расширяется E> для Списка

Наличие следующей простой структуры класса:

class A {
}

class B extends A {
}

class C extends B {
}

Я создаю ArrayList для хранения объектов ранее созданных классов:

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

К каждому из тех списков я пытаюсь добавить 1 объект каждого ранее созданного класса: A, B, C. Единственная возможная комбинация:

  • добавляя объект класса A, B, C к list4

  • добавление объекта класса B и C к list5

  • добавление объекта класса C перечислить list6. Остальная часть попыток дает ошибки компилятора, такой нас:

Метод добавляет (capture#1-of? расширяется A) в списке типов, не применимо для аргументов (A)

Почему я не могу добавить объект класса A, B, C к list1/2/3? Почему, например, list4 принимает объекты классов A, B, C, если они, как предполагается, являются суперклассом класса A, поскольку list4 определяется?

18
задан Ragunath Jawahar 16 October 2015 в 10:52
поделиться

5 ответов

"? extends A" means "some type derived from A (or A itself)". So for instance, a List is compatible with List - but you shouldn't be able to add a FileOutputStream to such a list - it's meant to be a List! All you know is that anything you fetch from the list will be an OutputStream of some kind.

"? super A" means "some type which is a superclass of A (or A itself)". So for instance, a List is compatible with List. You can definitely add a ByteArrayOutputStream to such a list - but if you fetch an item from the list, you can't really guarantee much about it.

See Angelika Langer's Generics FAQ for much more information.

14
ответ дан 30 November 2019 в 08:53
поделиться

Определение типа Список не может использоваться для изменяемого списка - объяснение, приведенное в Java generics Java Generics Pdf , равно

Метод add () принимает аргументы типа E, тип элемента коллекция. Когда фактический параметр типа?, Это означает какой-то неизвестный тип. Любой параметр мы передаем, чтобы добавить, должен быть подтип этого неизвестного типа. С тех пор, как мы не знаю что это за тип, мы не можем ничего передать.

Однако, когда typedef равен List тогда параметр типа? неявно типизирован.

4
ответ дан 30 November 2019 в 08:53
поделиться
List<? extends A> list1 

It is a list, whose type element could be any unknown subclass of A. For example, it could be a D subclass. Therefore, you can't add anything to it, it could be wrong...

List<? super A> list4

It is a list, whose type element could be A, or a superclass of A (does not exist in that case, except Object). Therefore, you can add A objects to it, or any subclass of A such as B or C.

2
ответ дан 30 November 2019 в 08:53
поделиться

It doesn't work that way.

You should use when you create function which argument is collection of unknown subtype of some type, and you want to fetch objects from that collection:

int sum(Collection<? extends Integer> collection) {
    for (Integer : collection) {
        // do sth
    }
    // ...
}

You cannot add new items to this collection, because you don't know which concrete type is this collection holding. All you know is that that type extends Integer.

You use when you want to add new items of type T to collection and return that collection, but then you cannot guarantee what you can retrieve from it and you have to cast result of get() or check its type. You can safely add items of type T and subtypes, and retrieve items of type T.

1
ответ дан 30 November 2019 в 08:53
поделиться

Список позволяет использовать списки любого супертипа B, то есть list5 = new ArrayList < A > (); or list5 = new ArrayList<Object>();

You can safely add B (and subtypes) to every list that use supertypes of B, but you can not add any supertype of B. Imagine this:

public void myAdd(List<? super B> lst) {
  lst.add(new Object()) //this is a supertype of B (compile time error)
}
...
ArrayList<A> list = new ArrayList<A>();
myAdd(list); //tries to add Object to a list of type A
0
ответ дан 30 November 2019 в 08:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: