Java mehrere generische Sammlungsparameter kompilieren Fehler

7

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 Typ     ArrayList<? 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?

    
Geln Yang 24.05.2010, 03:30
quelle

2 Antworten

17

Es gibt absolut keinen Fehler; Sie haben einfach die Subtyping-Regeln in Generika missverstanden.

Da wir B extends A :

haben
  • B ist ein Untertyp von A
  • ein instanceof B ist auch ein instanceof A

Da Java-Arrays kovariant sind:

  • B[] ist ein Untertyp von A[]
  • ein instanceof B[] ist auch ein instanceof A[]

Java-Generika sind jedoch invariant:

  • List<B> ist KEIN Untertyp von List<A>
  • 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.

Siehe auch

Verwandte Fragen

Bei generischen Tippregeln:

Bei Verwendung von super und extends :

Bei tatsächlichen generischen Fehlern:

polygenelubricants 24.05.2010, 04:17
quelle
9

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;.

    
CurtainDog 24.05.2010 03:45
quelle