2017-07-19 2 views
5

Ich versuche, etwas über die Verwendung von generischen Typen zu lernen und habe etwas seltsames bemerkt, als ich mit einigen Codezeilen experimentierte.Java - Generische Typen und Sammlungen

Der erste Teil des Codes ist innerhalb einer Klasse mit der Bezeichnung "A":

public void func(int k, List list) { 
    list.add(9); 
    list.add(true); 
    list.add("a string"); 
    } 

Das zweite Stück des Codes ist in einer anderen Klasse, in der Hauptfunktion:

List<Integer> arr = new ArrayList<Integer>(); 
     arr.add(14); 
     System.out.println(arr.toString()); 
     a.func(8, arr); 
     System.out.println(arr.toString()); 

des Laufes Code-Ergebnisse in diesen Linien gedruckt werden:

[14]

[14, 9, true, eine Zeichenfolge]

Die seit arr mir ziemlich verwirrt bekam eine ArrayList vom Typ Integer, wie es Objekte vom Typ boolean und String enthält? Gibt es eine Transformation der Liste in der Funktion func zu einem Rohtyp (was bedeutet, dass es vom generischen Typ Object wird)? Und wenn ja, wie ist das möglich, weil Sie das zum Beispiel nicht tun können: List<Integer> arr = new ArrayList<Object>();?

Würde mich etwas Klärung zu diesem Thema, vielleicht wird es mir helfen, dieses Thema der generischen Arten besser zu erfassen. Vielen Dank!

+0

Sie sollten lesen Sie über [raw types] erhalten (https://docs.oracle.com/javase/tutorial/ java/generics/rawTypes.html) und auch [Haufenverschmutzung] (https://docs.oracle.com/javase/tutorial/java/generics/nonRefabledVarargsType.html#heap_pollution). – Flown

Antwort

1

Java erlaubt nicht die Erstellung von generischen Arrays. Die Java Collection-Klassen werden hauptsächlich unter Verwendung von Object Arrays implementiert. Die Arraylist-Klasse wie folgt

public class ArrayList<T> implements List<T>, Serializable { 
    private transient Object[] data; 
    // more content... 
} 

aussehen kann, wenn eine neue Instanz der ArrayList ein neues Object[] Array erstellen erstellt, die Objekte jeder Art aufnehmen kann. Typensicherheit wird nur durch Verwendung des generischen Typparameters erreicht.

Da List keinen Typparameter zur Verfügung gestellt hat, wird rawtype verwendet und alles kann zur Liste hinzugefügt werden. Achten Sie deshalb immer darauf, Template-Argumente abzuleiten, um die Typsicherheit zu erhalten.

public void func(int k, List<Integer> list) { 
    list.add(9);  // works 
    list.add(true); // compile error 
    list.add("a string"); // compile error 
} 

Sie sollten niemals rawtypes verwenden. Abhängig von den Einstellungen Ihres Compilers werden Warnungen weggelassen. Es ist besser, (gebunden/ungebunden) Platzhalter zu verwenden.

1

Grund für diese Art von Ausgabe ist, dass Sie List als Parameter func(int k , List list) . Und Liste in func Methode ist nicht generisch, die Sie Zeichenfolge als auch hinzufügen können, so dass Sie eine solche Ausgabe bekommen sind vorbei.

1

Der ganze Punkt eines Generic-Codes in Java ist, Typ-Sicherheit vor der eigentlichen Code-Kompilierung bereitzustellen. Der kompilierte Code hat keinen Typ, deshalb haben wir kein Problem in unserem Code, da die func() Methode aufgerufen wird, die List arr hat keinen Typ.

Wenn wir System.out.println(arr.toString()) anrufen, drucken wir nur ein Objekt.Dies wird bei jedem Typ (d. H. Int, boolean, String usw.) in Ordnung gebracht. Aus diesem Grund gibt es keine Ausnahme.

jedoch nur versuchen, einen Wert aus dieser Liste zuweisen und wir werden java.lang.ClassCastException

... 
func(8, arr); 
System.out.println(arr.toString()); 
int a = arr.get(2);