Java - Generika
Es wäre schön, wenn wir eine einzelne Sortiermethode schreiben könnten, die die Elemente in einem Integer-Array, einem String-Array oder einem Array eines beliebigen Typs sortieren könnte, der die Reihenfolge unterstützt.
Java Generic Mithilfe von Methoden und generischen Klassen können Programmierer mit einer einzelnen Methodendeklaration eine Reihe verwandter Methoden bzw. mit einer einzelnen Klassendeklaration eine Reihe verwandter Typen angeben.
Generika bieten auch Typensicherheit zur Kompilierungszeit, mit der Programmierer ungültige Typen zur Kompilierungszeit abfangen können.
Unter Verwendung des generischen Java-Konzepts schreiben wir möglicherweise eine generische Methode zum Sortieren eines Arrays von Objekten und rufen dann die generische Methode mit Integer-Arrays, Double-Arrays, String-Arrays usw. auf, um die Array-Elemente zu sortieren.
Generische Methoden
Sie können eine einzelne generische Methodendeklaration schreiben, die mit Argumenten unterschiedlichen Typs aufgerufen werden kann. Basierend auf den Typen der Argumente, die an die generische Methode übergeben werden, behandelt der Compiler jeden Methodenaufruf entsprechend. Im Folgenden finden Sie die Regeln zum Definieren generischer Methoden:
Alle generischen Methodendeklarationen haben einen Typparameterabschnitt, der durch spitze Klammern (<und>) begrenzt ist und vor dem Rückgabetyp der Methode steht (<E> im nächsten Beispiel).
Jeder Typparameterabschnitt enthält einen oder mehrere durch Kommas getrennte Typparameter. Ein Typparameter, auch als Typvariable bezeichnet, ist ein Bezeichner, der einen generischen Typnamen angibt.
Die Typparameter können verwendet werden, um den Rückgabetyp zu deklarieren und als Platzhalter für die Typen der an die generische Methode übergebenen Argumente zu fungieren, die als tatsächliche Typargumente bezeichnet werden.
Der Körper einer generischen Methode wird wie der einer anderen Methode deklariert. Beachten Sie, dass Typparameter nur Referenztypen darstellen können, keine primitiven Typen (wie int, double und char).
Beispiel
Das folgende Beispiel zeigt, wie wir ein Array unterschiedlichen Typs mit einer einzigen generischen Methode drucken können.
public class GenericMethodTest {
// generic method printArray
public static < E > void printArray( E[] inputArray ) {
// Display array elements
for(E element : inputArray) {
System.out.printf("%s ", element);
}
System.out.println();
}
public static void main(String args[]) {
// Create arrays of Integer, Double and 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("Array integerArray contains:");
printArray(intArray); // pass an Integer array
System.out.println("\nArray doubleArray contains:");
printArray(doubleArray); // pass a Double array
System.out.println("\nArray characterArray contains:");
printArray(charArray); // pass a Character array
}
}
Dies führt zu folgendem Ergebnis:
Ausgabe
Array integerArray contains:
1 2 3 4 5
Array doubleArray contains:
1.1 2.2 3.3 4.4
Array characterArray contains:
H E L L O
Begrenzte Typparameter
Es kann vorkommen, dass Sie die Arten von Typen einschränken möchten, die an einen Typparameter übergeben werden dürfen. Beispielsweise möchte eine Methode, die mit Zahlen arbeitet, möglicherweise nur Instanzen von Number oder deren Unterklassen akzeptieren. Dafür sind begrenzte Typparameter gedacht.
Um einen begrenzten Typparameter zu deklarieren, listen Sie den Namen des Typparameters auf, gefolgt vom Schlüsselwort extens, gefolgt von seiner Obergrenze.
Beispiel
Das folgende Beispiel zeigt, wie Erweiterungen im Allgemeinen als "Erweiterungen" (wie in Klassen) oder "Implementierungen" (wie in Schnittstellen) bezeichnet werden. Dieses Beispiel ist eine generische Methode, um das größte von drei vergleichbaren Objekten zurückzugeben.
public class MaximumTest {
// determines the largest of three Comparable objects
public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
T max = x; // assume x is initially the largest
if(y.compareTo(max) > 0) {
max = y; // y is the largest so far
}
if(z.compareTo(max) > 0) {
max = z; // z is the largest now
}
return max; // returns the largest object
}
public static void main(String args[]) {
System.out.printf("Max of %d, %d and %d is %d\n\n",
3, 4, 5, maximum( 3, 4, 5 ));
System.out.printf("Max of %.1f,%.1f and %.1f is %.1f\n\n",
6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ));
System.out.printf("Max of %s, %s and %s is %s\n","pear",
"apple", "orange", maximum("pear", "apple", "orange"));
}
}
Dies führt zu folgendem Ergebnis:
Ausgabe
Max of 3, 4 and 5 is 5
Max of 6.6,8.8 and 7.7 is 8.8
Max of pear, apple and orange is pear
Generische Klassen
Eine generische Klassendeklaration sieht aus wie eine nicht generische Klassendeklaration, außer dass auf den Klassennamen ein Typparameterabschnitt folgt.
Wie bei generischen Methoden kann der Typparameterabschnitt einer generischen Klasse einen oder mehrere durch Kommas getrennte Typparameter enthalten. Diese Klassen werden als parametrisierte Klassen oder parametrisierte Typen bezeichnet, da sie einen oder mehrere Parameter akzeptieren.
Beispiel
Das folgende Beispiel zeigt, wie wir eine generische Klasse definieren können -
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("Hello World"));
System.out.printf("Integer Value :%d\n\n", integerBox.get());
System.out.printf("String Value :%s\n", stringBox.get());
}
}
Dies führt zu folgendem Ergebnis:
Ausgabe
Integer Value :10
String Value :Hello World