Wann sollten Platzhalter in Java Generics verwendet werden?
dies ist aus Kopfüber Java: ( Seite 575 )
:
public <T extends Animal> void takeThing(ArrayList<T> list)
Macht das gleiche wie dieses:
public void takeThing(ArrayList<? extends Animal> list)
So, hier ist meine Frage: wenn Sie sind genau die gleichen, warum wir nicht schreiben
public <? extends Animal> void takeThing(ArrayList<?> list)
oder
public void takeThing(ArrayList<T extends Animal> list)
Auch, wenn wäre es nützlich zu verwenden ? statt ein T in der Deklaration einer Funktion ( wie oben ) mit Generics, oder für eine Klasse Erklärung? Was sind die Vorteile?
InformationsquelleAutor der Frage Koray Tugay | 2013-05-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den großen Unterschied zwischen
und
ist, dass in der ehemaligen Methode finden Sie unter "T" innerhalb der Methode, wie die konkrete Klasse, die gegeben wurde. In der zweiten Methode können Sie nicht tun.
Hier ein komplexeres Beispiel um dies zu verdeutlichen:
Mit der ersten Methode, wenn Sie übergeben eine Liste von Katzen, die Sie bekommen eine Karte mit Katze als Schlüssel. Die zweite Methode würde immer wieder eine Karte mit Allgemeinen Tier Schlüssel.
Dies ist übrigens keine gültige java-syntax:
Verwendung dieser form der generischen Methode-Deklaration ein Gültiger java-Bezeichner sein und nicht "?".
Edit:
Form "? erstreckt Typ" gilt nur für Variablen oder parameter-Typ-Deklaration. Innerhalb einer generischen Methode declration es muss "Bezeichner erstreckt Typ", wie Sie in der Lage sind, verweisen auf die "Kennung" aus Ihrer Methode.
InformationsquelleAutor der Antwort Werzi2001
Wild cards sind über co/contra-Varianz von Generika. Ich werde versuchen, deutlich zu machen, was dies bedeutet, indem Sie einige Beispiele.
Grundsätzlich ist es im Zusammenhang mit der Tatsache, dass für die Typen S und T, wobei S ein Untertyp von T, der einen generischen Typ
G<S>
ist keine gültige Unterart desG<T>
Schaffen Sie Abhilfe mit wild cards
Bitte beachten Sie, dass Sie nicht setzen alles in so eine Liste
selbst (und eher überraschend für viele Entwickler):
Ich denke, SO ist nicht der richtige Ort, zu diskutieren, im detail. Ich werde versuchen zu finden, einige der Artikel und Beiträge, die diese näher erläutern.
InformationsquelleAutor der Antwort bennidi
Bindung der Art an einem Typ-parameter kann leistungsfähiger sein, je nachdem, was die Methode tun soll. Ich bin mir nicht sicher, was
takeThing
soll das tun, aber vorstellen, im Allgemeinen haben wir eine Methode, mit der man diese Art Unterschriften:Hier ist ein konkretes Beispiel von etwas, was Sie nur tun können, mit der ersten Typ Signatur:
In diesem Fall
T
ist verpflichtet, der Typ checker, das element entfernt aus der Liste ist ein OK-element hinzufügen auf der Liste.Könnte man dies nicht mit einem wildcard, weil, wie der Platzhalter hat, nicht gebunden an einen Typ-parameter, dessen Kontext nicht verfolgt (gut, es verfolgt wird, durch "einfangen", aber es ist nicht zu nutzen). Sie können mehr Informationen über diese in einer anderen Antwort habe ich gegeben: Wie Generika von Generika zu arbeiten?
InformationsquelleAutor der Antwort Mark Peters
Wenn Sie schreiben
? extends T
Sie sagen "alles, was ein T oder mehr spezifische". Zum Beispiel: einList<Shape>
kann nurShape
s eineList<? extends Shape>
könnenShape
sCircle
sRectangle
s, etc.Wenn Sie schreiben
? super T
Sie sagen "alles, was ein T oder mehr allgemein". Dies ist weniger Häufig genutzt, aber hat es Anwendungsfälle. Ein typisches Beispiel wäre eine callback: wenn Sie wollen, eineRectangle
zurück auf einen Rückruf, können SieCallback<? super Rectangle>
da einCallback<Shape>
wird in der Lage sein zu handhabenRectangle
s auch.Hier die entsprechenden Wikipedia-Artikel.
InformationsquelleAutor der Antwort Peter Becker
Wenn Ihr
takeThing
- Methode benötigt, um das hinzufügen von Elementen zurlist
parameter, die wildcard-version nicht kompilieren.Der interessante Fall ist, wenn Sie nicht hinzufügen, um der Liste und beide Versionen scheinen zu kompilieren und zu arbeiten.
In diesem Fall schreiben Sie die Platzhalter-version, wenn Sie möchten, dass verschiedene Art der Tiere, die in der Liste (mehr Flexibilität) und die parameter-version, wenn Sie benötigen eine Feste Art von Tier in der Liste: die T-Typ.
Beispielsweise die
java.util.Collection
erklärt:Und angenommen, Sie haben folgenden code:
Wenn die
java.util.Collection
wäre:Den oben genannten test-code würde nicht kompilieren und die Flexibilität der
Collection
API reduziert werden würde.Es erwähnenswert, dass die letztere definition von
containsAll
hat den Vorteil, fangen mehr Fehler zur compile-Zeit, zum Beispiel:Aber findet der gültigen test mit einem
Collection<Object> c = Arrays.<Object>asList(1, 2);
InformationsquelleAutor der Antwort dcernahoschi
Java Generics Wildcards Nutzung unterliegt den GET-PUT-Prinzip (auch bekannt als IN-OUT-Prinzip). Dieser besagt, dass:
"Erweitert" Platzhalter, wenn Sie nur Werte aus einer Struktur mit einem "super" - Platzhalter, wenn Sie nur Werte in einer Struktur, und verwenden Sie keine Platzhalterzeichen, wenn Sie beides tun. Dies gilt nicht für eine Methode Rückgabetyp. Nicht mit einem wildcard als Rückgabetyp. Siehe Beispiel unten:
InformationsquelleAutor der Antwort Rahul Saini