Es gibt eine Methode:
public static <T> void addandDisp(Collection<T> cs, T t)
wird wie folgt aufgerufen:
%Vor%Dies ergibt einen Kompilierzeitfehler. Auf der anderen Seite, wenn wir nur einen Parameter hatten, ist der Aufruf erfolgreich. Warum ist das so?
Außerdem ist das erfolgreich:
%Vor%dies ist nicht:
%Vor%Was ist die zugrunde liegende Logik?
Auf der anderen Seite, wenn wir nur einen Parameter hatten, ist der Aufruf erfolgreich. Warum ist das so?
Ihre Methode hat einen einzelnen Typparameter. Wenn Sie eine Methode aufrufen, geben Sie entweder explizit ein Typargument an oder leiten es implizit ab.
Wenn Sie es wie
aufrufen %Vor% Der Compiler muss einen Typ extrahieren, der von beiden Methodenargumenten an T
gebunden wird, da beide Methodenparameter vom Typparameter der Methode, T
, abhängig sind.
Das Problem hierbei ist, dass ? extends Object
und Object
keinen einzigen Typ erzeugen, der sicher an T
gebunden werden kann. Stell dir vor du hättest
Dieser add
sollte nicht erlaubt sein, da ein Object
nicht verwendet werden sollte, wenn ein Number
erwartet worden wäre. Type Sicherheit würde brechen.
Wenn Sie einen einzelnen Parameter haben
%Vor%Dann verwendet der Compiler das Argument Argument, um das Argument type zu ermitteln. Es gibt dann keine Zweideutigkeit darüber, was zu verwenden ist.
Ich würde annehmen, dass addandDisp
hinzufügen und anzeigen bedeutet.
Wenn Sie eine Sammlung haben, definiert als:
%Vor% Dies bedeutet, dass der Compiler es Ihnen erlaubt, die Sammlung allen möglichen unbekannten Subtypen von Object
zuzuweisen. Da Sie die Operation add
haben, verweigert Ihnen der Compiler grünes Licht, weil er nicht weiß, ob der Typ des angegebenen Objekts der Einschränkung des unbekannten Subtyps von Object entspricht. Dies wird Kovarianz genannt.
Ähnlich, wenn Sie eine solche Definition haben:
%Vor% Mit dem Compiler können Sie ls1
an:
LinkedList<String>(); //you can add Strings to the list
LinkedList<Object>(); //you can add Strings and Objects to the list
In diesem Fall erkennt der Compiler vollständig, ob das Objekt, das Sie übergeben möchten, die Bedingung erfüllt, dass es sich um den Subtyp des generischen Typs der Sammlung handelt. Dies nennt man Kontravarianz .
Weitere Informationen:
Hier ist ein anderer Ansatz, aber andere gaben eine ziemlich detaillierte Antwort.
Das erste Beispiel:
%Vor% Hier kann ls0
von jedem Typ sein, der eine Unterklasse von Object
ist, wie ein Number
, wie Ihr Beispiel zeigt.
Was wäre, wenn das funktionieren könnte? Es würde bedeuten, dass wenn Sie eine Object
in eine der Sammlungen einfügen können.
Stellen Sie sich vor, ich möchte Ihre vorherige Liste von Number
-Objekten iterieren:
Wenn ich hier ein Object
setzen könnte, dann Plaff! würde ich sofort eine Klassenausnahme erhalten.
Das zweite Beispiel
%Vor% Lassen Sie uns ein wenig mit der Objekthierarchie spielen: String
ist eine Unterklasse von CharSequence
, die eine Unterklasse von Object
ist.
Sie erhalten ls1
hier, was ein unbekannter Übertyp von String ist (z. B. ein CharSequence
). Ist es in Ordnung, ein String
in eine Liste von Zeichenfolgen zu setzen? Ja, es ist okay, da sie die gleiche Schnittstelle teilen! Du kannst sie auf dieselbe Art und Weise damit umgehen.
Das dritte Beispiel
%Vor% Nehmen wir die vorherige Situation an: Sie weisen ls1
eine Liste von CharSequence
s zu. Können Sie einem List<CharSequence>
ein Objekt hinzufügen? Nein, aus dem gleichen Grund wie das erste Beispiel fehlschlägt.
Hoffe, dass hilft, Ihre Probleme ein wenig zu klären: -)
1 Beispiel: Object
ist nicht ? extends Object
(z. B. Number
ist ? extends Object
, aber Object
ist nicht Number
). Daher ist es nicht typsicher.
2 Beispiel: String
ist ? super String
. Es ist typsicher.
3 Beispiel: Object
ist nicht ? super String
. Nicht wieder sicher.
Tags und Links java generics collections