2010-04-18 10 views
19

Ich habe Probleme, in dem folgenden Artikel zu verstehen: http://www.ibm.com/developerworks/java/library/j-jtp01255.htmlJava Generics Kovarianz

Under,

Generics nicht

Der Autor stellt fest,

Weil kovariant sind ln ist eine Liste und fügt einehinzu 210 Float dazu scheint völlig legal. Aber wenn ln mit li aliased wurde, dann es würde bricht die Typsicherheit verspricht implizit in der Definition von li - , dass es sich um eine Liste von ganzen Zahlen ist, die Deshalb generische Typen nicht covariant sein können.

Ich kann den Teil nicht verstehen, wo es "wenn ln aliased mit li" heißt. Was bedeutet der Autor mit Alias? (Referenz?). Das Code-Snippet über der zitierten Zeile scheint zu verdeutlichen, WAS in Java illegal ist und nicht in WHY. Es wäre sehr hilfreich für mich, wenn jemand mit einem Beispiel erklären könnte. Vielen Dank im Voraus.

+0

IIRC, generische Typen sind nicht covariant, weil sie nicht, wie Arrays wurden ändern könnte in früheren Versionen von Java (Abwärtskompatibilität) implementiert/verwendet, ist es eine Glocke läuten jemand? – Rhangaun

+0

@Skeptic, Arrays sind ein Beispiel dafür, wie eine kovariante Generika-Implementierung aussehen könnte - sie würde Laufzeitausnahmen auslösen. Java kann das nicht tun, da die Generika zur Laufzeit gelöscht werden, so dass sie nur über die begrenzende Kovarianz gesteuert werden können. – Yishai

+0

@ Yishai, dieses Problem mit Arrays wurde von Steele in einer Präsentation namens "Growing a Language" diskutiert, die ich gerade nicht zu finden scheint. – Rhangaun

Antwort

39
List<Integer> li = new ArrayList<Integer>(); 
List<Number> ln = li; // illegal 
ln.add(new Float(3.1415)); 

In Java erbt Integer von Number (java.lang.Number), so intuitiv, alles, was eine ganze Zahl ist (java.lang.Integer) ist auch eine Zahl, aber was dieser Artikel weist darauf hin, dass mit Generika es nicht so funktioniert, weil man bedenkt, dass Zum Beispiel könnten Sie einen Float (der eine Zahl ist) in eine List<Integer> setzen, was illegal ist, weil ein Float keine ganze Zahl ist.

Fazit: Generika sind nicht kovariant.

Hinweis: Ich empfehle Ihnen, lesen Effective Java (2nd Edition) Kapitel 5: Generics.

+0

Danke. 8) Ich dachte, die Erklärung hätte nichts mit dem Code-Snippet zu tun. Wie dumm von mir. – soocracy42

+0

+1 für die reco zu lesen Effektive Java. Ich schreibe seit vielen Jahren Code und habe EJ vor einem Monat abgeholt und sofort 5 oder 6 sehr wichtige Strategien gelernt. –

+0

Dieser Artikel ist auch immens hilfreich: https://www.ibm.com/developerworks/java/library/j-jtp01255/index.html –

8

Wenn Sie so etwas tun könnte:

List<Float> foo; 
List<Object> bar; 

foo = new ArrayList<Float>(); 
bar = foo; 

foo.add(1.0f); 
bar.add("Hello"); 

Dinge wäre sehr schief gehen. In diesem Beispiel ist bar ein Alias ​​für foo, und wenn Sie dies tun könnten, würden Sie die Typsicherheit verlieren, die der Hauptgrund dafür ist, dass Generika existieren.

+0

Vielen Dank. Ich war mir nicht sicher über den Alias-Teil. Dies bestätigt, dass meine Annahme richtig war. – soocracy42

+0

Ah! Also ist "Hallo" jetzt nicht nur in "bar" (was wahrscheinlich in Ordnung wäre), sondern auch in "foo". Endlich macht es Sinn :) Ich denke dann könnte ich eine Listencasting-Methode deklarieren, die die Liste kopieren müsste, hm. –

-2
public class vechicle { 
void drive(){ 
} 
} 
class car extends vechicle{ 
     //Covariance 
    vechicle getObject(){ 
     return new car(); 
    } 
     //contravariance 
    car getmyObject(){ 
     return (car) new vechicle(); 
    } 
} 
+0

java.lang.ClassCastException wird bei 'return (auto) new vechicle();' – Rembo