2016-05-23 14 views
1

Setup-Type Casting in Java parametrisiert Listen

Ich habe zwei Klassen:

class A { 

} 

class B extends A { 

} 

und eine Liste des Typs B:

List<B> listOfB = new ArrayList<>(); 

Teil 1: Ziel

Was ich effektiv versuche zu erreichen, ist, den Typ listOfB von B in A umzuwandeln. Im Anschluss an die Java tutorial, ich nehme an, dass der richtige Weg, dies zu tun, ist etwas entlang der Linien von:

List<? extends A> listOfB = new ArrayList<>(); 
listOfB.add(new B()); // <--- Error here 
List<A> listOfA = (List<A>) listOfB; 

Dies gilt jedoch nicht gestatten Sie mir, Objekte der Klasse A oder B-listOfB hinzuzufügen. Der Fehler, den ich bekommen ist:

hinzufügen (capture <? extends A>) in Liste kann nicht damit zu (B)

angewendet werden zugreifen ich derzeit auf die folgende Methode (das funktioniert völlig in Ordnung):

List<A> listOfA = new ArrayList<A>(listOfB); 

Teil 2: Effizienz

Offenbar gibt es keine So-gut-Wege, dies zu tun (link) und die empfohlene Art und Weise in den Java-Tutorials (link).

Also, was ist der richtige Weg, um dies mit List<? extends A> zu erreichen?

Und ich würde gerne den Leistungsverlust/Gewinn der oben genannten Methoden kennen. Spricht der Konstruktor den Gedanken listOfB, um Typumwandlung zu tun? Wenn ja, wirkt sich dies auf die Leistung aus, wenn die Liste größer wird (verglichen mit der direkten Typumwandlung in Teil 1)?

+2

Sie möchten vielleicht auf [PECS] nachlesen (http://stackoverflow.com/questions/2723397/what-is-pecs-producer-extends-consumer-super); es kann helfen zu erklären, was vor sich geht und warum. Was Ihren Teil 2 betrifft, wird der Konstruktor durch 'listOfB' iterieren, um Elemente in die neue ArrayList einzufügen, aber es ist keine Konvertierung involviert (und wäre auch nicht notwendig, da die Referenzen bereits vom Typ A sind). Der Konstruktor kopiert nur die Referenzen. – yshavit

Antwort

0

Die zweite ist der Weg zu gehen, ArrayList kann nur eine Array-Kopie der internen Daten.

Der Grund, warum ein B-List<? extends A> Zugabe ist nicht funktioniert, dass ? ein Subtyp von B oder Geschwister sein könnte. Es ist also unsicher, eine B hinzuzufügen.

heißt

class C extends A {} 
... 
List<? extends A> listOfC = new ArrayList<C>(); // perfectly valid 
listOfC.add(new B()); // uh oh, adding B to list of C!... 
1

Wenn Sie List <? extends A> schreiben die Bedeutung ist, dass einige unbekannte Art Elemente, die A erstrecken sich auf die Liste und nur Elemente dieses Typs befindet. Sie können keine Annahmen über den konkreten Typ der Elemente treffen, daher können Sie kein B zu Ihrer Liste hinzufügen. Sie können nichts hinzufügen, da der Compiler den konkreten Typ nicht kennt.

Wenn Sie List <B> definieren, bedeutet List, da es sich um Kovarianten in Java handelt, dass selbst wenn B A erweitert, List <B> nicht List <A>!Das macht Sinn: Wenn Sie das tun könnten, dann schauen Sie sich dieses Beispiel an: String extends Object right? Dann könnten Sie tun:

List <String> a = new List <>(); 
a.add ("bla"); 
List <Object> asObj = a; 
asObj.add (1); 

Und als wenn Sie versuchen, eine Sie glauben, eine Liste von Strings erhalten iterieren aber youll ein Classcast!

Also, die Frage ist, warum nicht Ihre Liste als Liste von As definieren?

Casting beinhaltet keine Konstruktoriteration. Der Compiler ersetzt die Typlöschungen vor der Laufzeit durch die konkreten Typen.