So seltsam! Bitte schauen Sie sich zuerst den Code an:
%Vor% Die Anweisung new TestMain().test(new ArrayList<B>(), new ArrayList<C>())
ruft einen Kompilierungsfehler ab:
Gebundene Diskrepanz: Der generische Methodentest (T, T) vom Typ TestMain ist nicht anwendbar für die Argumente
(ArrayList<B>, ArrayList<C>)
. Der abgeleitete TypArrayList<? extends A>
ist kein gültiger Ersatz für den beschränkten Parameter<T extends A>
Allerdings:
%Vor% Wenn wir das generische vor dem Methodennamen definieren, scheint der Typ des zweiten generischen List
-Parameters derselbe wie der erste zu sein. Aber es gibt keine Einschränkung, wenn wir generische Parameter definieren.
Ist es ein Feature oder ein Fehler des Kompilierprogramms? Gibt es eine Dokumentation darüber?
Es gibt absolut keinen Fehler; Sie haben einfach die Subtyping-Regeln in Generika missverstanden.
Da wir B extends A
:
B
ist ein Untertyp von A
instanceof B
ist auch ein instanceof A
Da Java-Arrays kovariant sind:
B[]
ist ein Untertyp von A[]
instanceof B[]
ist auch ein instanceof A[]
Java-Generika sind jedoch invariant:
List<B>
ist KEIN Untertyp von List<A>
instanceof List<B>
ist KEINE instanceof List<A>
. Wenn Sie die folgende allgemeine Methodendeklaration haben:
%Vor% Dann müssen a
und b
, wie hier explizit angegeben, für eine Capture-Konvertierung des Typs parameter List<T>
beide denselben Typ <T extends A>
haben.
Da List<B>
und List<C>
zwei verschiedene Typen sind, können Sie sie nicht als tatsächliche Argumente für test
verwenden. Auch wenn B
und C
Untertypen von A
sind, sind Generika invariant. Daher ist weder List<B>
noch List<C>
ein List<A>
.
Also,
%Vor%kompiliert nicht, was erwartetes Verhalten ist.
java.lang.ArrayStoreException
Bei generischen Tippregeln:
List<Animal> animals = new ArrayList<Dog>()
nicht tun kann? List
von List<Object>
unterscheidet, der sich von einem List<?>
unterscheidet
Bei Verwendung von super
und extends
:
Java Generics: What is PECS?
extends
consumer super
" super
in Java Generics extends
? und <E extends Number>
? <Number>
data structures hinzufügen? (SIE KÖNNEN NICHT!) Bei tatsächlichen generischen Fehlern:
Es ist kein Fehler, nur Generika sind komplex. Versuchen Sie, Ihre zweite Testmethode zu ändern:
%Vor%Im Grunde genommen gibt es keinen Typ T, der das, was Sie übergeben, erfüllen kann, im Gegensatz zur ersten Methode, bei der B und C nur als A behandelt werden. Der eigentliche Name für dieses Verhalten entgeht mir, aber es sollte viele Beispiele in der Literatur.
Kurz gesagt, obwohl B ein Kind von A ist, liste & lt; B & gt; ist kein Kind von List & lt; A & gt;.
Tags und Links java generics compiler-errors collections