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

Renzhentaxi Baerde
источник
Как может 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:

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

roottraveller
источник
«Таким образом, он может принимать типы, которые не наследуются от класса Object», но все классы Java наследуются или неявно наследуются от Objectкласса.
hackjutsu