Qual é a diferença entre <?> E <? estende Object> em Java Generics?

94

Já vi o caractere curinga usado antes para significar qualquer objeto - mas recentemente vi o uso de:

<? extends Object>

Uma vez que todos os objetos estendem Object, esses dois usos são sinônimos?

orbfish
fonte
2
É a mesma coisa. Consulte stackoverflow.com/questions/2274720/…
Dan
3
@Dan Se você pesquisar "? Extends Object" nessa questão, você não encontrará nada. Estou lendo as respostas para ver se consigo inferir alguma coisa, mas não acho que seja isso. Especificamente, não se trata de genéricos.
orbfish
@Dan - Essa é uma pergunta diferente. Já vi essa pergunta antes e me lembro de pelo menos uma menção a uma diferença sutil. Deixe-me ver se consigo encontrar.
Paul Bellora
Também não é este aqui se você encontrá-lo: stackoverflow.com/questions/678822/…
orbfish
1
Aqui vamos nós: possível duplicata de curingas ilimitadas em Java (apresentando uma resposta incorreta de Kevin Bourrillion nada menos.)
Paul Bellora

Respostas:

103

<?>e <? extends Object>são sinônimos, como você esperaria.

Existem alguns casos com genéricos em que extends Objectnão é realmente redundante. Por exemplo, <T extends Object & Foo>fará com Tque fique Objectsob apagamento, enquanto com <T extends Foo>ele ficará Foosob apagamento. (Isso pode ser importante se você estiver tentando manter a compatibilidade com uma API pré-genérica usada Object.)

Fonte: http://download.oracle.com/javase/tutorial/extra/generics/convert.html ; explica por que a java.util.Collectionsclasse do JDK tem um método com esta assinatura:

public static <T extends Object & Comparable<? super T>> T max(
    Collection<? extends T> coll
)
Ruakh
fonte
4
Não estou certo de como o exemplo se relaciona? (já que não usa <?> nem <? extends Object>)
orbfish
27
@orbfish: Relaciona-se apenas no sentido de que achei que você o acharia interessante, já que é um exemplo onde extends Objectrealmente é significativo. Se me enganei, peço desculpas. Esperançosamente, pelo menos, será do interesse de outras pessoas que tenham encontrado sua pergunta.
ruakh
@ruakh - Estava interessado em caracteres curinga limitados em vez de parâmetros de tipo, mas, pelo menos, você respondeu.
orbfish
1
Você deveria ter afirmado isso em sua postagem original. Dessa forma, a resposta dele poderia ter sido mais relevante para você.
liltitus27 de
19

Embora <?>deva ser um atalho para <? extend object>, há uma pequena diferença entre os dois. <?>é reificável enquanto <? extend object>não é. A razão pela qual fizeram isso é para facilitar a distinção entre tipos reificáveis. Qualquer coisa que se parece com <? extends something>, <T>, <Integer>são nonreifiable.

Por exemplo, este código funcionaria

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

mas isso dá um erro

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

para obter mais informações, leia os genéricos e coleções Java de Maurice Naftalin

Renzhentaxi Baerde
fonte
Como List <?> Pode ser reificável se o compilador irá traduzi-lo para List <Object> para informações sobre qual é o tipo de? está perdido?
Trismegistos
O que eu acredito <?> É mais projetado para compatibilidade com versões anteriores de APIs legadas. distinguir com <Objeto> e <? extends Object> que são códigos posteriores ao Java 5.
Dennis C
9

<?>é uma abreviação de <? extends Object>. Você pode ler o link compartilhado abaixo para obter mais detalhes.


<?>

"?"denota qualquer tipo desconhecido, pode representar qualquer tipo em no código para. Use este curinga se você não tiver certeza sobre o tipo.

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

Nota: <?> significa qualquer coisa. Portanto, pode aceitar Tipo que não seja herdado da Objectclasse.

<? extends Object>

<? extends Object>significa que você pode passar um objeto ou uma subclasse que estende a Objectclasse.

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

insira a descrição da imagem aqui

T - usado para denotar o tipo
E - usado para denotar o elemento
K - chaves
V - valores
N - para números
Ref:

insira a descrição da imagem aqui

roottraveller
fonte
"Portanto, pode aceitar Tipo que não seja herdado da classe Object", mas todas as classes Java são herdadas ou implicitamente herdadas da Objectclasse.
hackjutsu