Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Непонятки с генериками и super в частности


Автор: kaa 27.11.2011, 19:52
В общем есть два класса

Код

class MyClass1{}
class MyClass2 extends MyClass1{}


И есть код:

Код

List<? super MyClass2> lst = new LinkedList<MyClass1>();
lst.add( new MyClass1() );


Так вот, Eclipse мне подсвечивает метод add и пишет такую ошибку
Код

The method add(capture#1-of ? super MyClass2) in the type List<capture#1-of ? super MyClass2> is not applicable for the arguments (MyClass1)


Метод add у меня желает принимать только MyClass2 :(

Вопрос: почиму?; где я накосячил?

Автор: kaa 27.11.2011, 21:00
Нашёл ответ.

http://www.javabeat.net/tips/135-using-super-in-generics-java-50.html

Код

? super Dog means, the collection using this syntax can take either collection of same generic type or super generic type.


List<? super Dog> list1 = new ArrayList<Dog>();
List<? super Dog> list2 = new ArrayList<Animal>();
List<? super Dog> list3 = new ArrayList<Object>();

above three line will compile but not below line


List<? super Animal> list4 = new ArrayList<Dog>();

And now let us see what we can add to collection, if we use ? super syntax.

we can add same generic type or sub type of the generic type used in the declaration.

so we can add Animal or Cat or Dog to below collection


List<? super Animal> list = new ArrayList<Animal>();

Now the question is why we are allowed to add values to collection if we use ? super, which is not possible if we use ? extend ????????????.

the reason is, if we use ? super in collection declaration , the reference can point to same generic type of collection or super generic type of collection.

so if we add Animal or subtype of Animal to ? super Animal, the added value(Animal or subtype of it) will pass IS-A test with all types, which are super to Animal.

for example Dog will pass IS-A test with Animal and Object.

below code can explain everything in detail. assume class MyDog extends Dog.


List<? super Dog> list = new ArrayList<Dog>();
list.add(new Dog());
list.add(new MyDog());
list = new ArrayList<Animal>();
list.add(new Dog());
list.add(new MyDog());
list = new ArrayList<Object>();
list.add(new Dog());
list.add(new MyDog());

now how we can iterate this collection using enhanced for loop. 


Если вкратце: super позволяет инициализировать переменную, объявленную с супером, генериками с родительскими типами. которые выше по иерархии наследования, типами; но вот добавлять в саму коллекцию можно только объекты дочерних типов для декларации супер, при этом добавляемый объект автоматом тестируется на IS-A для всех родителей  super-а.

Громоздко как-то получилось... Ну, в статье там всё понятней, это выжимка smile

Автор: Sibit 28.11.2011, 05:21
А зачем может понадобиться такая фича?

Автор: kaa 29.11.2011, 15:14
Позволяет передавать типобезопасные коллекции куда-нить + оставляет возможность добавлять в них элементы. Например при использовании ключевого слова extends добавлять в коллекцию уже ничего нельзя - только получать из неё элементы.


Положа руку на сердце: ни разу такой фичей не пользовался. Я просто всё мечтаю SCJP сдать smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)