2016-09-14 1 views
5

Wir haben kürzlich einen Fehler in unserem Code gefunden, der im Wesentlichen mit OOP-Konzepten zusammenhängt.Geben Sie ein Objekt in einen Collection-Typ ein

class ABC 
{ 
    String a; 
    ABC(){ 
     a = "abc"; 
    } 
} 

public class Main { 


    static Object listABC() { 
     List<ABC> listOfABC = new ArrayList<>(); 
     listOfABC.add(new ABC()); 
     return listOfABC; 
    } 

    public static void main(String[] args) throws java.lang.Exception { 

     List<Long> listLong = (List) Main.listABC(); 
     System.out.println(listLong.get(0)); 
    } 
} 

Ausgabe: ABC @ 642c39d2

Sollte dies nicht eine Laufzeit Ausnahme auslösen? Kann mir jemand in die richtige Richtung weisen, warum nicht dieser Code eine Ausnahme auslöst?

+0

Ihre bestehende Liste ist Typ von und Sie sind es auf lange – Nimesh

+0

Ja, es keine Laufzeit Ausnahme – rmagon

+2

@rmagar, weil Generika nach dem Kompilieren gegangen sind. Sie erhalten keine "Runtime" -Ausnahme, weil der Compiler für den richtigen Typ sorgt. Wenn bei 'Runtime' etwas in einer anderen Klasse ist, die durch die Generika definiert wird, wird es keine Exposetion geben, da der generische Typ der' List' nicht mehr existiert. – SomeJavaGuy

Antwort

7

generische Typen werden gelöscht, und in Ihrem Beispiel Informationen über sie existiert nicht mehr zur Laufzeit. Sie sind nur eine Kompilierzeit Hilfe. Casting List < T> to List verwirft auch Informationen zum Typ zur Kompilierzeit, obwohl es immer noch eine gültige Besetzung ist.

Also solange Sie legal Casts bei jedem Schritt tun, was Sie sind, wird es gut kompilieren. Zur Laufzeit ist die Info über den Typ in der Liste hier weg.

Wenn Sie versucht haben, get (0) zu einem Long zu bekommen, dann erhalten Sie eine classcastexception, da das Element selbst ein ABC ist.

+3

Die eigentliche Geschichte ist komplexer, es ist besser zu sagen, dass _in diesem bestimmten Beispiel_, generische Typen weg sind. Zum Beispiel sind Typ-Parameter für ein Feld oder einen Methodenparameter für die Reflektion verfügbar. Wenn Sie eine generische Schnittstelle mit einer nicht-generischen Klasse implementieren, sind die von Ihnen verwendeten Literale ebenfalls verfügbar. In Java ist Löschen ein Durcheinander. –

+0

@Marko Ja. Nun, es ist eine große Dose Würmer. Aber ich kenne keinen besseren Weg, es zu formulieren. Ich füge ein "in diesem Beispiel" hinzu. Aber weitere Beschwerden müssen zu meiner Sekretärin gehen, lol. –

+0

@MarkoTopolnik kannst du bitte noch mehr Licht ablassen? Vielleicht weisen Sie mich auf einige gute Ressourcen hin? – rmagon

3

Die Antwort ist ziemlich einfach. Generics sind Kompilierzeitkomponenten, um die Kompilierzeitkompatibilität sicherzustellen. Generics sind nach dem Kompilieren weg und existieren somit nicht mehr zur Laufzeit.

Wie Object listABC zurückkehrt ein List, (List) Test.listABC(); Passt nicht auf eine Ausnahme aus, weil sein gültig, wie sie tatsächlich eine List zurückgibt.

können Sie es List<Long> listLong zuweisen, weil zur Laufzeit listLong nicht mehr über es Generic mehr bekannt ist.

Als Ergebnis ist dies, obwohl es falsch aussieht, gültiger ausführbarer Code.

auch der einzige Grund, diese Arbeit tut, ist, dass es eine PrintStream#println(Object) Methode, sonst du würdest ein Exception bekommen, weil Ihr versucht es mit einem falschen Typ zu nennen, wie Sie im folgenden Beispiel sehen kann.

static Object listABC() { 
    List<Test> listOfABC = new ArrayList<>(); 
    listOfABC.add(new Test()); 
    return listOfABC; 
} 

public static void main(String[] args) throws java.lang.Exception { 

    List<Long> listLong = (List) Test.listABC(); 
    System.out.println(listLong.get(0)); 
    test(listLong.get(0)); 
} 

private static void test(Long longvalue) { 
    System.out.println("TEST"); 
} 

O/P

[email protected] 
Exception in thread "main" java.lang.ClassCastException: ABC cannot be cast to java.lang.Long 
at ABC.main(ABC.java:19) 
Verwandte Themen