Heim > Java > javaLernprogramm > Hauptteil

Detaillierte Erklärung von Generika in Java

高洛峰
Freigeben: 2017-01-18 10:54:11
Original
1365 Leute haben es durchsucht

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<>();
Nach dem Login kopieren

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
Nach dem Login kopieren

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;
 
}
Nach dem Login kopieren

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());
 
}
Nach dem Login kopieren

Ausgabe

true
 
class java.util.ArrayList
 
class java.util.ArrayList
Nach dem Login kopieren

Typ-Wildcard

Zunächst muss klar sein, dass, wenn Foo die übergeordnete Klasse von Bar ist, List jedoch nicht die übergeordnete Klasse von List ist Übergeordnete Klassen: Java verwendet „?“, um generische Platzhalter darzustellen. Das heißt, List stellt die übergeordnete Klasse verschiedener allgemeiner Listen dar. Listen-Generika können keine Elemente festlegen (setzen), sondern nur abrufen (abrufen). Elemente. Da das Programm die Typen in der Liste nicht ermitteln kann, kann es keine Objekte hinzufügen. Das erhaltene Objekt muss jedoch vom Typ Objekt sein.

Die folgenden Methoden kompilieren Fehler:

List<?> list = new ArrayList<>();
 
list.add(new Object());
Nach dem Login kopieren

Einige Ideen:

1. List-Objekte können nicht verwendet werden Sprich: Die List-Klasse ist keine Unterklasse der 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 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); // 这里编译报错
    }
}
Nach dem Login kopieren

Der Grund für den Programmierfehler ist, dass List nicht die übergeordnete Klasse von List ist. Die erste Lösung besteht darin, den formalen Parameter List in der Methode getSize in List zu ändern. In diesem Fall ist jedoch bei jedem Abrufen des Objekts eine erzwungene Typkonvertierung erforderlich, was problematischer ist. Die Verwendung der Platzhalterobergrenze löst dieses Problem sehr gut. Sie können List in List ändern, und die Kompilierung wird nicht falsch sein und es ist keine Typkonvertierung erforderlich.


Untergrenze des Platzhalterzeichens

List 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:

修饰符 返回值类型 方法名(类形列表){
 
//方法体
 
}
Nach dem Login kopieren

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){ ...}
Nach dem Login kopieren

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-Typ in eine Liste konvertiert wird, wird die Typprüfung der Auflistungselemente der Liste zur Obergrenze der Typvariablen (d. h. Objekt). Diese Situation wird als Löschung bezeichnet.

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();  // ③
 
 }
 
}
Nach dem Login kopieren

Ausführlichere Artikel zu Generika in Java finden Sie auf der chinesischen PHP-Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!