Java-Generics

Java-Generics sind ein neues Feature, das in JDK 5 eingeführt wurde. Generics bieten einen Mechanismus zur Typsicherheitsprüfung zur Kompilierzeit, der es Programmierern ermöglicht, ungültige Typen zur Kompilierzeit zu erkennen.

Die Essenz von Generics sind parametrisierte Typen, das heißt, der Datentyp, mit dem gearbeitet wird, wird als Parameter angegeben.

Angenommen, wir haben eine Anforderung wie diese: Schreiben Sie eine Sortiermethode, die Integer-Arrays, String-Arrays oder sogar Arrays beliebiger anderer Typen sortieren kann. Wie kann dies implementiert werden?

Die Antwort ist die Verwendung vonJava-Generics。

Mithilfe des Konzepts der Java-Generics können wir eine generische Methode schreiben, um ein Objekt-Array zu sortieren. Rufen Sie dann diese generische Methode auf, um Integer-Arrays, Gleitkomma-Arrays, String-Arrays usw. zu sortieren.


Generische Methoden

Sie können eine generische Methode schreiben, die beim Aufruf Parameter unterschiedlicher Typen empfangen kann. Basierend auf den Typen der an die generische Methode übergebenen Argumente behandelt der Compiler jeden Methodenaufruf entsprechend.

Im Folgenden finden Sie die Regeln zum Definieren generischer Methoden:

  • Alle Deklarationen generischer Methoden haben einen Abschnitt zur Deklaration von Typparametern (in spitzen Klammern eingeschlossen). Dieser Abschnitt zur Deklaration von Typparametern erscheint vor dem Rückgabetyp der Methode (im folgenden Beispiel, der<E>)。
  • Jeder Deklarationsabschnitt für Typparameter enthält einen oder mehrere Typparameter, die durch Kommas getrennt sind. Ein generischer Parameter, auch als Typvariable bekannt, ist ein Bezeichner, der verwendet wird, um einen generischen Typnamen anzugeben.
  • Typparameter können verwendet werden, um Rückgabetypen zu deklarieren, und können als Platzhalter für die tatsächlichen Parametertypen dienen, die von der generischen Methode erhalten werden.
  • Die Deklaration eines generischen Methodenkörpers ist dieselbe wie bei anderen Methoden. Beachten Sie, dass Typparameter nur Referenztypen darstellen können, keine primitiven Typen (wie z. B.int、double、charusw.).

Generische Marker in Java:

  • E- Element (wird in Sammlungen verwendet, da Sammlungen Elemente speichern)
  • T- Typ (Java-Klasse)
  • K- Schlüssel
  • V- Wert
  • N- Zahl (numerischer Typ)
  • ?- repräsentiert einen unbestimmten Java-Typ

Beispiel

Das folgende Beispiel zeigt, wie man eine generische Methode verwendet, um Array-Elemente unterschiedlicher Typen auszugeben:

Beispiel

public class GenericMethodTest { //Generische Methode printArray public static < E > void printArray( E[] inputArray ) { //Ausgabe der Array-Elemente for ( E element : inputArray ){ System.out.printf( "%s ", element ); } System.out.println(); } public static void main( String args[] ) { //Erstellen von Arrays unterschiedlicher Typen: Integer, Double und Character Integer[] intArray = { 1, 2, 3, 4, 5 }; Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 }; Character[] charArray = { 'H', 'E', 'L', 'L', 'O' }; System.out.println( "Elemente des Integer-Arrays sind:" ); printArray( intArray ); //Übergabe eines Integer-Arrays System.out.println( "\nElemente des Double-Arrays mit doppelter Genauigkeit sind:" ); printArray( doubleArray ); //Übergeben eines Arrays mit doppelter Genauigkeit System.out.println( "\nDie Elemente des Zeichenarrays sind:" ); printArray( charArray ); //Übergeben eines Zeichenarrays } }

Kompilieren Sie den obigen Code, das Ausführungsergebnis lautet wie folgt:

整型数组元素为:
1 2 3 4 5 

双精度型数组元素为:
1.1 2.2 3.3 4.4 

字符型数组元素为:
H E L L O 

Begrenzte Typparameter:

Es kann vorkommen, dass Sie den Bereich der Typen einschränken möchten, die an einen Typparameter übergeben werden dürfen. Beispielsweise soll eine Methode, die mit Zahlen arbeitet, möglicherweise nur Instanzen von Number oder Unterklassen von Number akzeptieren. Dies ist der Zweck begrenzter Typparameter.

Um einen begrenzten Typparameter zu deklarieren, geben Sie zuerst den Namen des Typparameters an, gefolgt vom Schlüsselwort extends und dann von seiner Obergrenze.

Beispiel

Das folgende Beispiel zeigt, wie "extends" im allgemeinen Sinne von "extends" (Klassen) oder "implements" (Schnittstellen) verwendet wird. Die generische Methode in diesem Beispiel gibt das Maximum von drei vergleichbaren Objekten zurück.

Beispiel

public class MaximumTest { //Drei Werte vergleichen und das Maximum zurückgeben public static <T extends Comparable<T>> T maximum(T x, T y, T z) { T max = x; //Angenommen, x ist das anfängliche Maximum if ( y.compareTo( max ) > 0 ){ max = y; //y ist größer } if ( z.compareTo( max ) > 0 ){ max = z; //Jetzt ist z größer } return max; //Das maximale Objekt zurückgeben } public static void main( String args[] ) { System.out.printf( "Die größte Zahl von %d, %d und %d ist %d\n\n", 3, 4, 5, maximum( 3, 4, 5 ) ); System.out.printf( "Die größte Zahl von %.1f, %.1f und %.1f ist %.1f\n\n", 6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) ); System.out.printf( "Die größte Zeichenkette von %s, %s und %s ist %s\n","pear", "apple", "orange", maximum( "pear", "apple", "orange" ) ); } }

Kompilieren Sie den obigen Code, das Ausführungsergebnis lautet wie folgt:

3, 4 和 5 中最大的数为 5

6.6, 8.8 和 7.7 中最大的数为 8.8

pear, apple 和 orange 中最大的数为 pear

Generische Klassen

Die Deklaration einer generischen Klasse ähnelt der einer nicht-generischen Klasse, außer dass nach dem Klassennamen ein Abschnitt zur Deklaration von Typparametern hinzugefügt wird.

Wie bei generischen Methoden enthält auch der Abschnitt zur Deklaration von Typparametern einer generischen Klasse einen oder mehrere Typparameter, die durch Kommas getrennt sind. Ein generischer Parameter, auch als Typvariable bekannt, ist ein Bezeichner, der verwendet wird, um einen generischen Typnamen anzugeben. Da sie einen oder mehrere Parameter akzeptieren, werden diese Klassen parametrisierte Klassen oder parametrisierte Typen genannt.

Beispiel

Das folgende Beispiel zeigt, wie wir eine generische Klasse definieren:

Beispiel

public class Box<T> { private T t; public void add(T t) { this.t = t; } public T get() { return t; } public static void main(String[] args) { Box<Integer> integerBox = new Box<Integer>(); Box<String> stringBox = new Box<String>(); integerBox.add(new Integer(10)); stringBox.add(new String("Example")); System.out.printf("Integer-Wert: %d\n\n", integerBox.get()); System.out.printf("String: %s\n", stringBox.get()); } }

Kompilieren Sie den obigen Code, das Ausführungsergebnis lautet wie folgt:

整型值为 :10

字符串为 :Example

Typ-Wildcards

1. Typ-Wildcards werden im Allgemeinen verwendet?, um bestimmte Typparameter zu ersetzen. Zum BeispielList<?>ist logischList<String>,List<Integer>und alleList<spezifische Typargumente>Elternklassen.

Beispiel

import java.util.*; public class GenericTest { public static void main(String[] args) { List<String> name = new ArrayList<String>(); List<Integer> age = new ArrayList<Integer>(); List<Number> number = new ArrayList<Number>(); name.add("icon"); age.add(18); number.add(314); getData(name); getData(age); getData(number); } public static void getData(List<?> data) { System.out.println("data :" + data.get(0)); } }

Das Ausgabeergebnis ist:

data :icon
data :18
data :314

Analyse:Weil beigetData()der Methodenparameter vom TypList<?>ist, dahername,age,numberkönnen alle als Argumente für diese Methode verwendet werden; das ist die Funktion von Wildcards.

2. Die obere Grenze des Typ-Wildcards wird durch die Form List

Beispiel

import java.util.*; public class GenericTest { public static void main(String[] args) { List<String> name = new ArrayList<String>(); List<Integer> age = new ArrayList<Integer>(); List<Number> number = new ArrayList<Number>(); name.add("icon"); age.add(18); number.add(314); //getUperNumber(name);//1 getUperNumber(age);//2 getUperNumber(number);//3 } public static void getData(List<?> data) { System.out.println("data :" + data.get(0)); } public static void getUperNumber(List<? extends Number> data) { System.out.println("data :" + data.get(0)); } }

Ausgabeergebnis:

data :18
data :314

Analyse:In//1Ein Fehler wird an der Position auftreten, weilgetUperNumber()der Parameter in der Methode bereits die generische Obergrenze des Parameters aufNumber, sodass der generische TypStringnicht in diesem Bereich liegt, daher wird ein Fehler gemeldet.

3. Die untere Grenze des Typplatzhalters wird durch die FormList<? super Number>definiert, was bedeutet, dass der Typ nurNumberund dessen darüberliegende Oberklassentypen akzeptieren kann, wie z. B.ObjectInstanzen des Typs.

Andere Erweiterungen