Die sogenannten Generika: Sie ermöglichen die Angabe von Typparametern beim Definieren von Klassen und Schnittstellen. Dieser Typparameter wird beim Deklarieren von Variablen und beim Erstellen von Objekten bestimmt (d. h. bei der Übergabe tatsächlicher Typparameter, die auch als Typargumente bezeichnet werden können).
Generische Klasse oder Schnittstelle
"Diamond"-Syntax
//定义 public interface List<E> extends Collection<E> public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable //使用 List<String> list = new ArrayList(); //Java7以后可以省略后面尖括号的类型参数 List<String> list = new ArrayList<>();
Ableitung einer Unterklasse von einer generischen Klasse
//方式1 public class App extends GenericType<String> //方式2 public class App<T> extends GenericType<T> //方式3 public class App extends GenericType
Pseudo-generisch
Es gibt keine echte generische Klasse. Die JVM kennt die Existenz generischer Klassen und gewöhnlicher Klassen. Daher sind Typparameter in statischen Methoden, statischen Initialisierungsblöcken und statischen Variablen nicht zulässig.
- Die folgenden Methoden sind alle falsch
private static T data; static{ T f; } public static void func(){ T name = 1; }
Das folgende Beispiel kann von der Seite aus überprüfen, dass es keine generische Klasse gibt
public static void main(String[] args){ List<String> a1 = new ArrayList<>(); List<Integer> a2 = new ArrayList<>(); System.out.println(a1.getClass() == a2.getClass()); System.out.println(a1.getClass()); System.out.println(a2.getClass()); }
Ausgabe
true class java.util.ArrayList class java.util.ArrayList
Typ-Wildcard
Zunächst muss klar sein, dass, wenn Foo die übergeordnete Klasse von Bar ist, List
Die folgenden Methoden kompilieren Fehler:
List<?> list = new ArrayList<>(); list.add(new Object());
Einige Ideen:
1. List
2. Arrays und Generics sind unterschiedlich: Angenommen, Foo ist ein Untertyp (Unterklasse oder Unterschnittstelle) von Bar, dann ist Foo[] immer noch ein Untertyp von Bar[]; ;Bar>.
3. Um die übergeordnete Klasse verschiedener generischer Listen darzustellen, müssen wir Typ-Wildcards verwenden, um ein Fragezeichen als Typargument zu übergeben , schreiben: Liste<> (bedeutet Liste von Elementen unbekannten Typs). Dieses Fragezeichen (?) wird als Platzhalterzeichen bezeichnet und sein Elementtyp kann mit jedem beliebigen Typ übereinstimmen.
Die Obergrenze der Platzhalter
List erweitert SuperType> repräsentiert die übergeordnete Klasse aller generischen SuperType-Listen oder sich selbst. Generics mit Wildcard-Obergrenzen können keine Set-Methoden haben, sondern nur Get-Methoden.
Das Festlegen der Obergrenze für Platzhalter kann die folgenden Probleme lösen: Dog ist eine Animal-Unterklasse und es gibt eine getSize-Methode, um die Anzahl der eingehenden Listen abzurufen. Der Code lautet wie folgt:
abstract class Animal { public abstract void run(); } class Dog extends Animal { public void run() { System.out.println("Dog run"); } } public class App { public static void getSize(List<Animal> list) { System.out.println(list.size()); } public static void main(String[] args) { List<Dog> list = new ArrayList<>(); getSize(list); // 这里编译报错 } }
Der Grund für den Programmierfehler ist, dass List
Untergrenze des Platzhalterzeichens
List super SubType> stellt die Untergrenze der generischen SubType-Liste dar. Generika mit Platzhalter-Obergrenzen können keine Get-Methoden haben, sondern nur Set-Methoden.
Generische Methoden
Wenn Sie Klassen und Schnittstellen definieren, ohne Typparameter zu verwenden, aber beim Definieren von Methoden selbst Typparameter definieren möchten, bietet JDK1.5 auch Unterstützung für generische Typmethoden . Die Methodensignatur einer generischen Methode enthält mehr Typparameterdeklarationen als die Methodensignatur einer gewöhnlichen Methode. Die Typparameterdeklarationen werden durch Kommas (,) getrennt Modifikatoren und Methodenrückgabewerttypen Das Syntaxformat lautet wie folgt:
修饰符 返回值类型 方法名(类形列表){ //方法体 }
Generische Methoden ermöglichen die Verwendung von Typparametern, um Typabhängigkeiten zwischen einem oder mehreren Parametern der Methode oder die Typabhängigkeit zwischen Methoden auszudrücken Rückgabewert und Parameter. Wenn keine solche Typabhängigkeit besteht, sollten generische Methoden nicht verwendet werden. Die Kopiermethode von Collections verwendet die generische Methode:
public static <T> void copy(List<? super T> dest, List<? extends T> src){ ...}
Diese Methode erfordert, dass der src-Typ eine Unterklasse des dest-Typs oder sich selbst sein muss.
Löschen und Konvertieren
In streng generischem Code sollten Klassen mit generischen Deklarationen immer Typparameter tragen. Um jedoch mit altem Java-Code konsistent zu sein, ist es auch erlaubt, Klassen mit generischen Deklarationen ohne Angabe von Typparametern zu verwenden. Wenn für diese generische Klasse kein Typparameter angegeben ist, wird der Typparameter als Rohtyp bezeichnet und verwendet standardmäßig den ersten Obergrenzentyp, der bei der Deklaration des Parameters angegeben wurde.
Wenn ein Objekt mit generischen Informationen einer anderen Variablen ohne generische Informationen zugewiesen wird, werden alle Typinformationen in spitzen Klammern verworfen. Wenn beispielsweise ein List
Beispiel
class Apple<T extends Number> { T size; public Apple() { } public Apple(T size) { this.size = size; } public void setSize(T size) { this.size = size; } public T getSize() { return this.size; } } public class ErasureTest { public static void main(String[] args) { Apple<Integer> a = new Apple<>(6); // ① // a的getSize方法返回Integer对象 Integer as = a.getSize(); // 把a对象赋给Apple变量,丢失尖括号里的类型信息 Apple b = a; // ② // b只知道size的类型是Number Number size1 = b.getSize(); // 下面代码引起编译错误 Integer size2 = b.getSize(); // ③ } }
Ausführlichere Artikel zu Generika in Java finden Sie auf der chinesischen PHP-Website!