2013-11-23 5 views

ответ

6
ArrayList<? extends Object> 

является такой же, как только

ArrayList<?> 

и вы можете назначить любойArrayList переменной этого типа. Например,

ArrayList<? extends Object> list = new ArrayList<String>(); 

является законным. Ясно, что семантика языка не позволит вам добавить Object в такой список. Фактически, они не позволят вам добавить что-нибудь вообще, кроме null, или что-то, что вы непосредственно извлекли из списка.

Как отметил Лукас в комментарии, далеко не тривиально даже добавить к нему собственный элемент списка: вам нужен вспомогательный метод для захвата подстановочного знака в именованный тип.

public static void main(String[] args) { 
    ArrayList<? extends Object> list = new ArrayList<String>(); 
    addOwn(list); 
} 
static <T> void addOwn(List<T> l) { l.add(l.get(0)); } 
+0

* или что-то, что вы непосредственно извлекли из списка. *: Это меня удивит. Можете ли вы показать пример? :-) –

+0

Я с Лукасом на этом. Пожалуйста, покажите пример. –

+0

@ LukasEder Пример показан. –

2

Я думаю, причина в том, что Общие типы не являются полиморфными. Когда вы используете wildcards ? с расширениями, вы не можете добавить что-либо в коллекцию, кроме null.

Вот пример того, что произойдет, если это разрешено:

Class Car{ 

} 
class A extends Car { 

} 
class B extends Car{ 

} 

Теперь у вас есть List<? extends Car>

public void someMethod(List<? extends Car> list){ 
list.add(new A()); //this is not valid 
} 

Также вы можете вызвать метод как это:

List<B> someList = new Array:list<B>(); 
somemethod(someList); 
2

Проблема заключается в том, что Foo extends Object не означает, что Collection<Foo> может рассматриваться как подтип Collection<Object>. Это просто потому, что прежний класс не позволяет вам делать все, что делает последний; например, вы не можете добавить Object в Collection<Foo>. Использование дженериков вместо какого-то конкретного класса Foo не меняет этого.

Смежные вопросы