В чем разница между <?> И <? расширяет 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.