2017-05-27 5 views
0

Say .., die Java-Compiler alle Arten Informationen löschen, und ersetzt alle Vorkommen von denen, mit ihren oberen Grenzen (falls angegeben) oder Objekt ..Java Generics - Löschungen Mechanismus

Meine Fragen ist: keine Einblendung von Abgüssen findet hier statt. Casting tritt zu einem späteren Zeitpunkt auf, wenn eine andere Klasse gegen diese Art von Klasse ohne Informationen kompiliert wird, wobei die generische Klasse (je nach Typargument oder anderen Klassenergänzungen) (zum zweiten Mal) neu kompiliert wird und alle Umwandlungen implementiert werden und die Klasse ist bereit für die Laufzeit .., oder?

Antwort

4

Nein, die Klasse wird nicht neu kompiliert. Die Umwandlungen finden an der Grenze zwischen konkreten und generischen Typen statt.

Wenn Sie versuchen, es herauszufinden, könnten Sie eine generische Klasse als Rohtyp verwenden (d. H. Ohne die Generika). Zum Beispiel ArrayList:

List l = new ArrayList(); // An `ArrayList<String>` before generics. 

l.add("Hello"); 
String s = (String) l.get(0); 

Die Abgüsse eingefügt sind, wo der Beton-Typ (String in diesem Fall) bekannt ist. Sie sind nicht in der ArrayList Klasse eingefügt, und es gibt nicht wirklich eine Notwendigkeit dafür.

+0

Danke. Also sind die Umwandlungen wirklich innerhalb der Benutzerklasse, nicht die generische Klasse, richtig? Auch in Bezug auf Ihr Beispiel oben wäre die Umwandlung in String, die explizit dort eingefügt wurde, automatisch vom Java-Compiler eingefügt worden, wenn wir die Liste angegeben haben, richtig? – Searcherer

+2

@Searcherer Ja, die Umwandlungen sind in der Benutzerklasse. Das Löschen von 'ArrayList's Typparameter ist' Object', aber nur in der Benutzerklasse benötigen Sie einen spezifischeren Typ, daher wird dort gewirkt. Und ja, dieser Cast wird automatisch bei 'ArrayList ' eingefügt. Beachten Sie, dass für die 'add'-Methode kein Cast vorliegt. –

+0

Vielen Dank.Ich möchte nur noch eine kleine letzte Frage stellen: In Bezug auf Ihre Anmerkung, dass für die add -Methode keine Umwandlung vorgesehen ist, kickt der Compiler immer noch das Argument gegen die Signatur von add, die je nach type-Parameter variieren kann und somit ungültige Argumente zurückweist . Recht? – Searcherer

0

Casting kommt später, wenn eine andere Klasse gegen diese Art zusammengestellt Info frei Klasse,

Nein, die Besetzung bei der Erstellung Phase der Klasse selbst durchgeführt wird.
Die kompilierte Klasse sollte sich nicht entsprechend den Klassen ändern, von denen sie abhängt.

Schauen Sie sich diese Methode:

public class TestCast { 

    public void doSomething(){ 
     List<Integer> values = new ArrayList<>(); 
     values.add(1); 
     Integer value = values.get(0); 
    } 
} 

Hier ist die Demontage Methode der TestCast kompilierte Klasse (done mit javap Werkzeug):

public void doSomething(); 
    Code: 
     0: new   #15     // class java/util/ArrayList 
     3: dup 
     4: invokespecial #17     // Method java/util/ArrayList."<init>":()V 
     7: astore_1 
     8: aload_1 
     9: iconst_1 
    10: invokestatic #18     // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 
    13: invokeinterface #24, 2   // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z 
    18: pop 
    19: aload_1 
    20: iconst_0 
    21: invokeinterface #30, 2   // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object; 
    26: checkcast  #19     // class java/lang/Integer 
    29: astore_2 
    30: return 

Die Besetzung in der Tat vom Compiler hinzugefügt wird:

26: checkcast  #19     // class java/lang/Integer 
0

Etwas anderes othe Die bisher erwähnten Antworten sind Bridge-Methoden.

z.B.

public class GenericTest implements Comparable<GenericTest>{ 

    @Override 
    public int compareTo(GenericTest o) { 
     return 0; 
    } 
} 

Der Compiler wird tatsächlich zwei Methoden erstellen. int compareTo(Object); das wirft und vorwärts und die erwartete int compareTo(GenericTest)