2016-04-09 17 views
1

Ich lese auf Generics in Java ATM, und die Dinge gehen ein wenig langsam würde gerne etwas Hilfe. Ich las von Oracles eigene Datenbank:Generics Java Wildcards und Subtyping

https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html

Am unteren wir List<Integer> ist ein Subtyp von List<? extends Number>

ich auch kam in dieser Stackoverflow Frage sehen:

Java Generic type : difference between List <? extends Number> and List <T extends Number>

Welche sagt in einer Antwort: das ist wahr:

((List<Integer>)list).add((int) s); 

Ich habe es verifiziert, also ist das in Ordnung. Aber ich verstehe es nicht vollständig.

Was ist, wenn die Wildcard die Short-Klasse ist und ich eine Zahl höher als 2^15-1 (= 32767) hinzufügen. Sollte es keinen Fehler geben?

Ich habe sogar versucht, so etwas wie dieses und es funktioniert gut:

import java.util.*; 
class CastingWildcard{ 
    public static void main(String[] args){ 
     List<? extends Number> list = new ArrayList<Short>(); 
     int s=32770; 
     ((List<Integer>)list).add((int) s); 
     System.out.println(list.get(0)); 
    } 
} 

Fazit: Warum kann ich List<? extends Number>-List<Integer> werfen, wenn die Platzhalter könnte kurz sein, und sogar Byte, die auch Nummer erstreckt?

Antwort

1

Durch die Umwandlung ignoriert der Compiler die Tatsache, dass die Typen möglicherweise nicht zuweisbar sind.

Zur Laufzeit sind die Typparameter unwichtig, siehe type erasure.

Die ArrayList speichert intern den Inhalt in einem Object[] Array, was bedeutet, dass Sie einen beliebigen Referenztyp zum Listenobjekt hinzufügen können, wenn Sie Casting "missbrauchen".

Sie erhalten möglicherweise eine Ausnahme, wenn Sie ein Objekt abrufen, da in der Anweisung get eine Umwandlung verborgen ist.

Beispiel:

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3)); 
List<String> list2 = (List) list; 
list2.add("Hello World"); 

Integer i = list.get(0); // works 
String s = list2.get(3); // works 
s = list2.get(1); // ClassCastException 
i = list.get(3); // ClassCastException 
+0

Danke für die Antwort. Ich werde es später anschauen. – martius

+0

Was bedeutet Gießen (Liste) ohne Typ? Ist es gleich zu "Liste list2 = (Liste ) (Objekt) Liste" in Ihrer zweiten Zeile dort? Davon ableitend: http://stackoverflow.com/questions/1917844/how-to-cast-listobject-to-listmyclass – martius

1

Sie können ein Objekt beliebig transformieren, es kann jedoch zur Laufzeit fehlschlagen. Da jedoch während der Laufzeit keine Generika-Informationen vorhanden sind, wird Ihr Code im Wesentlichen ((List)list).add(s);. An diesem Punkt list wird irgendein Objekt nehmen, nicht nur ein Number. Generics können Ihnen dabei helfen, Umwandlungen zu vermeiden und die Typensicherheit während der Kompilierzeit beizubehalten, aber während der Laufzeit spielen sie keine Rolle mehr.

+0

Danke für die Antwort. Ich werde es später anschauen. – martius