Unterschied zwischen ? (Platzhalter), und Geben Sie Parameter in Java
Kann jemand mir erklären, was der Unterschied ist zwischen diesen beiden Methoden? Sind Sie gleich? Aussehen tun Sie gleich zu mir in Bezug auf das, was Sie lösen. Wenn Sie gleich sind, warum brauchen ?
?
Methode #1, Unbegrenzte
public static void printList(List<?> list) {
for (Object elem : list)
System.out.println(elem + " ");
System.out.println();
}
Methode #2, Unbounded:
public static <T> void printList(List<T> list) {
for (Object elem : list)
System.out.println(elem + " ");
System.out.println();
}
Methode #1, Begrenzt
public static void printList(List<? extends Number> list) {
for (Object elem : list)
System.out.println(elem + " ");
System.out.println();
}
Methode #2, Begrenzt:
public static <T extends Number> void printList(List<T> list) {
for (Object elem : list)
System.out.println(elem + " ");
System.out.println();
}
- Ich weiß, aber meine Frage ist über Generika in Methoden.
- Die Antwort liegt auf halbem Weg nach unten dieses tutorial.
- Können Sie bitte schreiben Sie eine eigentliche Antwort statt Kommentar, so dass ich annehmen kann, Ihre Antwort, da es die Antwort, die ich gesucht habe.
- Jason C wohl besser gesagt, als ich hätte. Viel Glück!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sind Sie gleich, dass Sie akzeptiert die gleichen parameter-Typen.
Jedoch, welche die Art mit
T
(oder was auch immer), können Sie beziehen sich auf die Art anderswo.Edit: Beispiele:
Ihre unbounded Beispiele nicht machen, vollen Gebrauch von den Fähigkeiten von parametrisierten Typen. Sie haben:
... Und das ist ausreichend für das Beispiel der Druck-string-Darstellungen, aber Bedenken Sie diese (sehr gekünstelt, und keine Fehlerbehandlung):
Ist der Rückgabetyp T, das können Sie bedenkenlos tun, Dinge wie diese, mit compile-Zeit-Typ-überprüfung:
Einen Namen geben Sie können Sie auch teilen die gleiche Art Einschränkung an mehreren stellen, z.B.:
Wenn Sie nicht der Typ sind, könnten Sie nicht angeben, die Einschränkung, dass
a
undb
sind der gleichen Liste geben (Sie könnte verwendenList<? extends T>
für mehr Flexibilität).Sie auch gefragt, "Warum brauche ich
?
?". Die richtige Antwort ist: Sie nicht. Es ist vor allem für die ästhetik, nehme ich an. Java ist bestrebt, zu einer präzisen und schnörkellosen Sprache. Es gibt viele Situationen, in denen Sie einfach nicht darauf, welche Art Sie sich beziehen. In diesen Fällen dürfen Sie?
ohne überladen code mit ungenutzten Typ parameter-Deklarationen.?
??
? Ich denke, dies war auch in der ursprünglichen Frage.void op (List<? extends Base> a, List<? extends Base> b)
stattvoid <T extends Base, U extends Base> op (List<T> a, List<U> b)
.static final List<?> MY_LIST;
könnte nicht mit einem Typ-parameter statt. Es gibt auch geschachtelte Platzhalter, die ganz andere Semantik. Eine Methodevoid m(List<List<?>> l)
unterscheidet sich von<T> void m(List<List<T>> l)
.<?>
", tatsächlich es ist der code, den wir schreiben können mit<?>
dass wir nicht schreiben können (die in eine Typ-sichere Art), ohne es. Siehe das Beispiel mitList<Set<?>>
in dieser Antwort: stackoverflow.com/a/10777906 Ohne<?>
Sie müssten, um zu verwenden <Object> und das wäre nicht typsicher ist.In deiner Beispiele, es gibt absolut überhaupt keinen Unterschied. Jeder wird die gleiche Ausgabe erzeugen.
Die optimale Nutzung und interpretation von Generika erforderlich, dass Sie wissen, wie die Semantik der type-parameter sowie etwas über die parameter der Rolle. Der Grund dafür ist, dass in einem Fall wie deinem ersten Beispiel oben (unbounded Wildcard) die Semantik "eine Liste von Objekten unbekannter Typ" und "parameter zu erzeugen (nicht konsumieren)
List<?>
Instanzen.Der oben genannten Methode einfach produziert jeder
List<?>
- Objekt und rufttoString()
auf jeden. Alle Objekte sind garantiert eintoString()
Methode und so ist es nicht notwendig zu wissen überhaupt etwas über den Typ des Objekts für diesen Zweck. Dies ist genau der Grund, warum die unbounded wildcard ist die beste Wahl für diese Methode parameter: produzierenList<?>
Instanzen und der AufruftoString()
auf Sie, es ist nicht notwendig zu wissen, etwas über den Typ des Objekts.Beachten Sie, dass, wenn die
?
hatte das gleiche Semantik ("eine Liste der Objekte unbekannten Typs") oder aber einem anderen Zweck ("die Liste würde verbrauchen Objekte unbekannten Typs"), was würde sich ändern, sehr, sehr radikal, so dass es möglicherweise nicht ratsam (oder sehr schwer) zu wildcard-parameter (zumindest ohne eine helper-Methode zum erfassen der Objekt-Typ).Generell ist es nicht möglich zu behaupten, einen generischen parameter form für alle Situationen. Die beste form zu verwenden (wildcard vs. Beton; begrenzt vs. unbegrenzt; erstreckt vs. super) hängt sowohl von der Semantik der parameter " Typ " und was die Rolle der parameter in der Methode sein wird.
Wie oben erwähnt, die
?
Staaten, die der generische code benötigt keine Referenz auf einen Typ. Wie bereits in der Java-Trails, das könnte eine Klasse sein, in denen die Eigenschaften sind unabhängig von jeder Art wie beispielsweise die Länge einer Sammlung.Ein weiterer Grund für die
?
ist, dass es eine syntax für weniger Mehrdeutigkeit für den Fall, wenn der generische code muss nur Verhalten vom class-Objekt. Wie oben erwähnt, haben die parameter-Typ<T>
funktionieren würde, aber die Tatsache, dass T definiert wurde, und dann nie verwendet, könnte suggerieren, dass die Entwickler sich etwas.Also, wenn
<T>
fallen gelassen, weil der semantischen Mehrdeutigkeit und<?>
ist nicht verfügbar, dann würde der Entwickler versucht sein zu schreiben<Object>
. Dies ist jedoch nicht erlaubt, die generischen code verwendet werden, der für jede Art, nur den Objekt-Typ.So,
<?>
genauer.<?>
sehr eindeutig selbst dokumentiert, dass der Typ absichtlich nicht anderweitig verwendet werden.