Ich habe vor zwei Tagen eine Codeüberprüfung für meinen Kollegen durchgeführt. Ich hatte das Gefühl, dass ich kein gutes Verständnis für Java -Generika hatte, also nahm ich das Buch "Effektives Java" 1 heraus und schaute mir dann die relevanten Kapitel an. In Punkt 24: Beseitigen Sie den Abschnitt "Unkontrollierte Warnungen", verwendet der Autor die öffentliche <t> t [] ToArray (t [] a) Methode in der ArrayList -Klasse als Beispiel, um zu veranschaulichen, wie @SuppressWarnings Annotation für Variablen verwendet werden.
ArrayList ist eine generische Klasse, die so deklariert wird:
Javapublic Class ArrayList <E> Erweitert AbstractList <E> implementiert die Liste <E>, randomaccess, klonbar, java.io.Serializable
Die Methode TOARRAY (T [] A) dieser Klasse ist eine generische Methode, die so deklariert und implementiert wird:
@SuppressWarnings ("Unkontrolliert") public <t> t [] toArray (t [] a) {if (a.Length <Größe) // Erstellen Sie ein neues Array von A -Laufzeittyp von A, aber meine Inhalte: return (t []) Arrays Größe) a [Größe] = NULL; Return a;} Diese Methode wird tatsächlich in der Sammlungsschnittstelle deklariert. Da wir es oft über ArrayList verwenden, verwenden wir hier ArrayList als Beispiel.
1 Warum wird es als anderer Typ deklariert?
Meine Frage lautet: Warum verwendet diese Methode Typ T anstelle von Typ E von ArrayList? Das heißt, warum wird diese Methode nicht so deklariert:
Javapublic E [] TOARRAY (E [] A);
Wenn die Typen gleich sind, kann der Parametertypfehler während der Kompilierung gefunden werden. Wenn die Typen unterschiedlich sind, ist es einfach, Laufzeitfehler zu generieren. Zum Beispiel der folgende Code:
// Erstellen Sie eine arrayListList <strlist> strlist = new ArrayList <strlist> (); strlist.add ("abc"); Strlist.add ("xyz"); // Die aktuelle Strlist in ein Zahlenarray konvertieren. Beachten Sie, dass in der folgenden Anweisung keine Kompilierungsfehler vorhanden sind. Number [] numarray = strlist.toArray (neue Nummer [0]); Führen Sie den obigen Code aus und Zeile 6 wirft eine Ausnahme von java.lang.ArrayStoreException aus.
Wenn die TOARRAY -Methode Typ E verwendet, generiert Anweisung 2 einen Kompilierungsfehler. Kompilierungsfehler sind freundlicher als Laufzeitfehler. Darüber hinaus besteht der Hauptzweck von Generika darin, die Typ -Conversion -Fehler (ClassCastException) während der Zusammenstellung zu beseitigen. Diese Methode ist das Gegenteil. Ist das ein großer Fehler? Ich bin auf einen Java -Fehler gestoßen, aber ich kann es immer noch nicht glauben.
Nach der Überprüfung des Internets wurde dieses Problem viele Male 2, 3, 4 besprochen.
2 kann die Flexibilität verbessern
Diese Erklärung ist flexibler und kann Elemente in der aktuellen Liste in eine Reihe allgemeinerer Typen umwandeln. Zum Beispiel ist der aktuelle Listentyp ganzzahlig und wir können seine Elemente in ein Zahlenarray umwandeln.
List <Gesinger> intList = new ArrayList <GanzEger> (); intList.add (1); intlist.add (2); number [] numarray = intList.toArray (neue Nummer [0]);
Wenn diese Methode als Typ E deklariert wird, hat der obige Code einen Kompilierungsfehler. Es scheint, dass es angemessener wäre, die Methode wie folgt zu erklären:
Javapublic <t super e> t [] toArray (t [] a);
In Java existiert jedoch Syntax wie <t Super e> nicht. Und selbst wenn es existiert, funktioniert es für Arrays nicht. Aus diesem Grund ist es auch, dass bei Verwendung dieser Methode, auch wenn es t die übergeordnete Klasse von E oder T ist, mit E, Java.lang.ArrayStoreException 5, 6, 7 nicht vollständig vermieden werden. Bitte beachten Sie die folgenden zwei Codes. Im ersten Code ist T die übergeordnete Klasse von E, und im zweiten Code ist T dieselbe wie E. Beide Code -Treffer -Ausnahmen.
Code 1:
List <Gearner> intList = new ArrayList <Integer> (); intList.add (1); intList.add (2); Float [] floatArray = new float [2]; // float ist eine Unterklasse der Zahl, also ist float [] eine Unterklasse der Zahl [] number [] numarray = floatArray; // Die folgende Anweisung wirft eine ArrayStoreException -Ausnahme Numarray = intList.toarray (Numarray).
Code 2:
List <Number> intList = new ArrayList <Nummer> (); // Der Typ der Liste ist die Nummer. Zahl ist jedoch eine abstrakte Klasse und kann nur Instanzen ihrer Unterklasse intist.add (New Integer ()) speichern; intList.add (New Integer ()); Float [] floatArray = new float []; // float ist eine Unterklasse der Zahl, also ist float [] eine Unterklasse der Zahl [] number [] numarray = floatArray; // Die folgende Anweisung wirft eine ArrayStoreException -Ausnahme Numarray = intList.toarray (Numarray);
Die obigen Ausnahmen werden alle durch diese Tatsache verursacht: Wenn a die übergeordnete Klasse von B ist, dann ist A [] die übergeordnete Klasse von B []. Alle Klassen in Java erben aus Objekt, und Object [] ist die übergeordnete Klasse aller Arrays.
Dieser Beitrag 8 zeigt ein Beispiel: Auch wenn der Typ dieser Methode als E deklariert wird, kann die ArrayStoreException nicht vermieden werden.
Diese Ausnahme wird auch in der Dokumentation für diese Methode erwähnt:
ArrayStoreException Wenn der Laufzeittyp des angegebenen Arrays kein Supertyp des Laufzeittyps jedes Elements in dieser Liste ist.
3 Es kann mit Versionen vor Java 1.5 kompatibel sein
Diese Methode erschien vor der Einführung von Generika in Java (Generics wurde in JDK1.5 eingeführt). Es wurde damals deklariert:
Javapublic Object [] toArray (Objekt [] a)
Nachdem Generika erscheint, werden viele Klassen und Methoden generisch. Diese Methode deklariert es auch wie folgt:
Javapublic <t> t [] toArray (t [] a)
Diese Erklärung ist mit Versionen vor Java 1.5 kompatibel.
4 Ein paar weitere Wörter
Diese Methode erfordert einen Array -Parameter. Wenn die Länge dieses Arrays größer oder gleich der Größe der aktuellen Liste ist, werden die Elemente in der Liste im Array gespeichert. Wenn die Länge dieses Arrays geringer ist als die Größe der aktuellen Liste, wird ein neues Array erstellt und die Elemente in der aktuellen Liste werden im neu erstellten Array gespeichert. Um die Effizienz zu verbessern, muss die Länge des übergebenen Arrays nach Möglichkeit größer oder gleich der Größe der Liste sein, um zu vermeiden, dass ein neues Array nach dieser Methode erstellt wird.
List <Gesinger> intList = new ArrayList <GanzEger> (); intist.add (); intList.add (); // Einfügen in einem Array, seine Länge ist Nummer [] numArray = intList.toArray (neue Nummer []); // Anweisung // In ein Array einfügen, seine Länge entspricht der Länge der intellistischen Nummer [] numarray = intList.toArray (neue Nummer [intlist.size ()]); //Stellungnahme
Darüber hinaus kann das Array als Parameter nicht null sein, sonst wird eine NullPointerexception geworfen.
Fußnoten:
1
Effektive Java (2. Ausgabe)
2
Link
3
Link
4
Link
5
Link
6
Link
7
Link
8
Link
9
Link
10
Link
Erstellt: 2016-04-06 Mi 21:14
EMACS 24.5.1 (Org -Modus 8.2.10)
Bestätigen
Der obige Inhalt ist der Grund, warum die vom Editor vorgestellte Methode der Java -ArrayList (T []) der Parametertyp.