Die erste Unterschrift sagt: list1 ist eine Liste von Es.
Die zweite Signatur sagt: Liste ist eine Liste von Instanzen eines Typs, aber wir kennen den Typ nicht.
Der Unterschied wird deutlich, wenn wir versuchen, die Methode zu ändern, so dass es ein zweites Argument, das in die Liste innerhalb der Methode hinzugefügt werden soll:
import java.util.List;
public class Experiment {
public static <E> void funct1(final List<E> list1, final E something) {
list1.add(something);
}
public static void funct2(final List<?> list, final Object something) {
list.add(something); // does not compile
}
}
Die erste gut funktioniert. Und Sie können das zweite Argument nicht in etwas ändern, das tatsächlich kompiliert wird.
Eigentlich fand ich nur noch schöner Beweis für die Differenz:
public class Experiment {
public static <E> void funct1(final List<E> list) {
list.add(list.get(0));
}
public static void funct2(final List<?> list) {
list.add(list.get(0)); // !!!!!!!!!!!!!! won't compile !!!!!!!!!
}
}
Man könnte als warum brauchen wir <?>
wenn es schränkt nur das, was wir damit machen können (wie @Babu_Reddy_H in den Kommentaren tat) . Ich sehe die folgenden Vorteile der Wildcard-Version:
Der Anrufer weniger über das Objekt zu wissen, hat er in passiert zum Beispiel, wenn ich eine Karte von Listen haben. Map<String, List<?>>
ich ihre Werte an Ihre Funktion übergeben können, ohne Angabe des Typs der Listenelemente. Also
Wenn ich so parametrisierte Objekte austeile, beschränke ich aktiv, was die Leute über diese Objekte wissen und was sie damit machen können (solange sie sich vom unsicheren Casting fernhalten).
Diese beiden ergeben Sinn, wenn ich sie kombiniere: List<? extends T>
. Betrachten Sie zum Beispiel eine Methode List<T> merge(List<? extends T>, List<? extends T>)
, die die beiden Eingabelisten zu einer neuen Ergebnisliste zusammenführt. Sicher könnten Sie zwei weitere Typparameter einführen, aber warum sollten Sie das wollen? Es wäre zu viel, Dinge zu spezifizieren.
- schließlich können Platzhalter untere Grenzen haben, so mit Listen können Sie die
add
Methode funktioniert, während get
nicht geben Sie etwas Nützliches. Das löst natürlich die nächste Frage aus: Warum haben Generika keine unteren Grenzen?
Für eine eingehende Antwort siehe: When to use generic methods and when to use wild-card? und http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ203
Wenn String auf 'java.lang.String' verweist, denke ich, dass funct2 in den Wildcard-Ausdrücken recht redundant ist, da' java.lang.String' finale Klasse ist und nicht erweitert werden kann. – nhahtdh
Das ist merkwürdig, weil Sie String technisch nicht erweitern können, da es eine letzte Klasse ist. –
jedoch gibt es keine Einschränkung für die Verwendung von Funktion 2: wie es Unterklassen von String erlaubt (obwohl unmöglich) oder die String-Klasse selbst ... – ria