В чем разница между <?> И <? расширяет Object> в Java Generics?


96

Я видел подстановочный знак, который раньше использовался для обозначения любого объекта, но недавно видел использование:

<? extends Object>

Поскольку все объекты расширяют Object, являются ли эти два использования синонимами?


2
Это то же самое. См. Stackoverflow.com/questions/2274720/…
Дэн

3
@Dan Если вы введете в этот вопрос поисковый запрос "? Extends Object", вы ничего не найдете. Я читаю ответы, чтобы узнать, могу ли я что-нибудь сделать, но я не думаю, что это все. В частности, речь не идет о дженериках.
orbfish 08

@Dan - Это другой вопрос. Я видел этот вопрос раньше и помню, по крайней мере, упоминание о тонкой разнице. Дай мне посмотреть, смогу ли я его найти ..
Пол Беллора

Это тоже не этот, если вы его найдете: stackoverflow.com/questions/678822/…
orbfish

1
Вот и мы: возможный дубликат неограниченных подстановочных знаков в Java (включая неверный ответ Кевина Бурриллиона)
Пол Беллора

Ответы:


104

<?>и <? extends Object>являются синонимами, как и следовало ожидать.

Есть несколько случаев с дженериками, которые на extends Objectсамом деле не являются избыточными. Например, <T extends Object & Foo>приведет к тому , Tчтобы стать Objectпод стиранием, в то время как с <T extends Foo>он станет Fooпод стиранием. (Это может иметь значение, если вы пытаетесь сохранить совместимость с используемым ранее созданным API Object.)

Источник: http://download.oracle.com/javase/tutorial/extra/generics/convert.html ; он объясняет, почему у java.util.Collectionsкласса JDK есть метод с этой подписью:

public static <T extends Object & Comparable<? super T>> T max(
    Collection<? extends T> coll
)

4
Я не понимаю, как связан этот пример? (поскольку он не использует ни <?>, ни <? extends Object>)
orbfish

27
@orbfish: Это относится только в том , что я думал , что вы нашли это интересным, так как это пример , где на extends Objectсамом деле является значимым. Если я ошибся, то прошу прощения. Надеюсь, это заинтересует, по крайней мере, других людей, столкнувшихся с вашим вопросом.
ruakh 08

@ruakh - Меня интересовали ограниченные символы подстановки, а не параметры типа, но, по крайней мере, вы ответили.
orbfish

1
Тогда вы должны были заявить об этом в своем исходном посте. Таким образом, его ответ мог бы быть более актуальным для вас.
liltitus27 07

19

Хотя <?>предполагается, что это ярлык <? extend object>, между ними есть небольшая разница. <?>реифицируем, а <? extend object>нет. Причина, по которой они сделали это, состоит в том, чтобы облегчить различение реифицируемого типа. Все , что выглядит как <? extends something>, <T>, <Integer>являются nonreifiable.

Например, этот код будет работать

List aList = new ArrayList<>();
boolean instanceTest = aList instanceof List<?>;

но это дает ошибку

List aList = new ArrayList<>();
boolean instancetest = aList instanceof List<? extends Object>;

для получения дополнительной информации прочтите обобщения и коллекции Java от Мориса Нафталина.


Как может List <?> Быть реифицируемым, если компилятор переведет его в List <Object>, чтобы получить информацию о типе? потерян?
Трисмегиста

Я считаю, что <?> Больше предназначен для обратной совместимости с устаревшими API. различать с помощью <Object> и <? расширяет Object>, который является кодом Java 5.
Dennis C

9

<?>это сокращение от <? extends Object>. Вы можете прочитать ссылку ниже для более подробной информации.


<?>

"?"обозначает любой неизвестный тип. Он может представлять любой тип в коде для. Используйте этот подстановочный знак, если вы не уверены в типе.

ArrayList<?> unknownList = new ArrayList<Number>(); //can accept of type Number
unknownList = new ArrayList<Float>(); //Float is of type Number

Примечание: <?> означает что угодно. Таким образом, он может принимать типы, которые не унаследованы от Objectкласса.

<? extends Object>

<? extends Object>означает, что вы можете передать объект или подкласс, расширяющий Objectкласс.

ArrayList<? extends Number> numberList = new ArrayList<Number>(); //Number of subclass
numberList = new ArrayList<Integer>(); //Integer extends Number
numberList = new ArrayList<Float>(); // Float extends Number 

введите описание изображения здесь

T - используется для обозначения типа
E - используется для обозначения элемента
K - ключей
V - значений
N - для чисел
Ref:

введите описание изображения здесь


«Таким образом, он может принимать типы, которые не наследуются от класса Object», но все классы Java наследуются или неявно наследуются от Objectкласса.
hackjutsu
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.