Jaka jest różnica między <?> I <? rozszerza Object> w Java Generics?

96

Widziałem wcześniej używany symbol wieloznaczny oznaczający dowolny obiekt - ale ostatnio widziałem użycie:

<? extends Object>

Ponieważ wszystkie obiekty rozszerzają Object, czy te dwa zastosowania są synonimami?

orbfish
źródło
2
To jest to samo. Zobacz stackoverflow.com/questions/2274720/…
Dan
3
@Dan Jeśli wyszukujesz „? Extends Object” w tym pytaniu, nic nie znajdziesz. Czytam odpowiedzi, aby zobaczyć, czy mogę coś wywnioskować, ale nie sądzę, że to jest to. W szczególności nie chodzi o leki generyczne.
orbfish
@Dan - To inne pytanie. Widziałem już to pytanie i pamiętam przynajmniej wzmiankę o subtelnej różnicy.
Zobaczę,
To też nie jest ten, jeśli go znajdziesz: stackoverflow.com/questions/678822/ ...
orbfish
1
Zaczynamy: możliwy duplikat nieograniczonych symboli wieloznacznych w Javie (zawiera co najmniej niepoprawną odpowiedź Kevina Bourrilliona)
Paul Bellora

Odpowiedzi:

104

<?>i <? extends Object>są synonimami, jak można się spodziewać.

Istnieje kilka przypadków, w których leki generyczne extends Objectnie są w rzeczywistości zbędne. Na przykład <T extends Object & Foo>spowoduje, że Tstanie się on Objectwymazany, podczas gdy wraz z <T extends Foo>nim zostanie Foowymazany. (Może to mieć znaczenie, jeśli starasz się zachować zgodność z używanym przedgenerycznym interfejsem API Object).

Źródło: http://download.oracle.com/javase/tutorial/extra/generics/convert.html ; wyjaśnia, dlaczego java.util.Collectionsklasa JDK ma metodę z tym podpisem:

public static <T extends Object & Comparable<? super T>> T max(
    Collection<? extends T> coll
)
ruakh
źródło
4
Nie wiem, jak odnosi się ten przykład? (ponieważ nie używa ani <?>, ani <? extends Object>)
orbfish
27
@orbfish: Odnosi się to tylko do tego, że myślałem, że uznasz to za interesujące, ponieważ jest to przykład, w którym w extends Objectrzeczywistości ma znaczenie. Jeśli się pomyliłem, przepraszam. Miejmy nadzieję, że zainteresują go przynajmniej inne osoby, które napotkają Twoje pytanie.
ruakh
@ruakh - interesowały mnie ograniczone symbole wieloznaczne, a nie parametry typu, ale przynajmniej odpowiedziałeś.
orbfish
1
Powinieneś wtedy to zaznaczyć w swoim oryginalnym poście. W ten sposób jego odpowiedź mogłaby być dla ciebie bardziej odpowiednia.
liltitus27
19

Chociaż <?>ma to być skrót <? extend object>, istnieje między nimi niewielka różnica. <?>jest reifable, podczas gdy <? extend object>nie jest. Powodem, dla którego to zrobili, jest ułatwienie rozróżnienia typów reifiable. Wszystko, co wygląda <? extends something>, <T>, <Integer>są nonreifiable.

Na przykład ten kod zadziała

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

ale to daje błąd

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

Aby uzyskać więcej informacji, przeczytaj artykuł generyczny i kolekcje Java autorstwa Maurice'a Naftalina

Renzhentaxi Baerde
źródło
W jaki sposób List <?> Może być reifable, jeśli kompilator przetłumaczy go na List <Object>, więc informacje o tym, jakiego typu jest? zgubiony?
Trismegistos
Co moim zdaniem <?> Jest bardziej zaprojektowane pod kątem zgodności wstecznej ze starszymi interfejsami API. rozróżniać za pomocą <Object> i <? rozszerza Object>, które są po kodzie Java 5.
Dennis C,
9

<?>jest skrótem dla <? extends Object>. Możesz przeczytać poniżej udostępniony link, aby uzyskać więcej informacji.


<?>

"?"oznacza dowolny nieznany typ, może reprezentować dowolny typ w kodzie. Użyj tego symbolu wieloznacznego, jeśli nie masz pewności co do typu.

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

Uwaga: <?> oznacza cokolwiek. Może więc akceptować typy, które nie są dziedziczone z Objectklasy.

<? extends Object>

<? extends Object>oznacza, że ​​możesz przekazać Object lub podklasę, która rozszerza Objectklasę.

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

wprowadź opis obrazu tutaj

T - używany do oznaczenia typu
E - używany do oznaczenia elementu
K - klucze
V - wartości
N - dla liczb
Ref:

wprowadź opis obrazu tutaj

roottraveller
źródło
„Więc może akceptować typy, które nie są dziedziczone z klasy Object”, ale wszystkie klasy Java są dziedziczone lub niejawnie dziedziczone z Objectklasy.
hackjutsu