Heim > Java > javaLernprogramm > Implementierungsprinzipien von Java-Generika

Implementierungsprinzipien von Java-Generika

高洛峰
Freigeben: 2016-12-19 15:47:18
Original
1438 Leute haben es durchsucht

1. Einführung in Java Generics

Generics sind eine neue Funktion von Java 1.5. Das Wesentliche an Generics ist ein parametrisierter Typ, was bedeutet, dass der zu bedienende Datentyp als Parameter angegeben wird. Dieser Parametertyp kann bei der Erstellung von Klassen, Schnittstellen und Methoden verwendet werden, die als generische Klassen, generische Schnittstellen bzw. generische Methoden bezeichnet werden.

Der Vorteil der Einführung von Java-Generika besteht darin, dass sie sicher und einfach sind.

Vor Java SE 1.5 wurden die „willkürlichen“ Parameter durch Verweisen auf den Typ „Object“ implementiert. Der Nachteil von „willkürlich“ bestand darin, dass eine explizite Typkonvertierung erforderlich war, und diese Konvertierung erfordert die Bitten Sie den Entwickler, den tatsächlichen Parametertyp im Voraus zu kennen. Bei erzwungenen Typkonvertierungsfehlern löst der Compiler möglicherweise keinen Fehler aus und es tritt während der Laufzeit eine Ausnahme auf. Dies stellt ein Sicherheitsrisiko dar.

Der Vorteil von Generika besteht darin, dass die Typsicherheit während der Kompilierung überprüft wird und alle Umwandlungen automatisch und implizit erfolgen, was die Wiederverwendung von Code verbessert.

Es gibt einige Regeln und Einschränkungen bei der Verwendung von Generika:

1 Die Typparameter von Generika können nur Klassentypen (einschließlich benutzerdefinierter Klassen) sein, nicht jedoch ein einfacher Typ.

2. Derselbe generische Typ kann mehreren Versionen entsprechen (da der Parametertyp unsicher ist) und verschiedene Versionen generischer Klasseninstanzen nicht kompatibel sind.

3. Generics können mehrere Typparameter haben.

4. Generische Parametertypen können beispielsweise die Extens-Anweisung verwenden. Üblicherweise werden sie zu „begrenzten Typen“.

5. Generische Parametertypen können auch Platzhaltertypen sein.

Class<?> classType = Class.forName(java.lang.String);
Nach dem Login kopieren

Generika haben auch Schnittstellen, Methoden usw. Es gibt viele Inhalte und es erfordert viel Aufwand, sie zu verstehen und geschickt anzuwenden.

2. Java-Generika-Implementierungsprinzip: Typlöschung

Java-Generika sind Pseudo-Generika. Beim Kompilieren werden alle generischen Informationen gelöscht. Die erste Voraussetzung für das richtige Verständnis des Konzepts der Generika ist das Verständnis der Typlöschung.

Generics in Java werden grundsätzlich auf Compiler-Ebene implementiert. Die Typinformationen in Generics sind nicht im generierten Java-Bytecode enthalten. Bei der Verwendung von Generika hinzugefügte Typparameter werden vom Compiler während der Kompilierung entfernt. Dieser Vorgang wird als Typlöschung bezeichnet.

Im Code definierte Typen wie List werden nach der Kompilierung in List programmiert. Alles, was die JVM sieht, ist die Liste, und die durch Generics angehängten Typinformationen sind für die JVM unsichtbar. Der Java-Compiler wird sein Bestes tun, um mögliche Fehler zur Kompilierungszeit zu finden, er kann jedoch Ausnahmen bei der Typkonvertierung zur Laufzeit dennoch nicht vermeiden. Typlöschung ist auch ein wichtiger Unterschied zwischen der generischen Implementierungsmethode von Java und der Implementierungsmethode des C++-Vorlagenmechanismus (später beschrieben).

3. Der ursprüngliche Typ, der nach der Typlöschung erhalten bleibt

Der ursprüngliche Typ (Rohtyp) ist der tatsächliche Typ der Typvariablen im Bytecode, nachdem die generischen Informationen gelöscht wurden. Immer wenn ein generischer Typ definiert wird, wird der entsprechende primitive Typ automatisch bereitgestellt. Typvariablen werden gelöscht (crased) und durch ihren qualifizierten Typ ersetzt (nicht qualifizierte Variablen sind Objekt).

class Pair<T> {    
  private T value;    
  public T getValue() {    
    return value;    
  }    
  public void setValue(T  value) {    
    this.value = value;    
  }    
}
Nach dem Login kopieren

Der ursprüngliche Typ von Pair ist:

class Pair {    
  private Object value;    
  public Object getValue() {    
    return value;    
  }    
  public void setValue(Object  value) {    
    this.value = value;    
  }    
}
Nach dem Login kopieren

Da T in Pair eine undefinierte Typvariable ist, wird sie durch Object ersetzt. Das Ergebnis ist eine normale Klasse, so wie Generika implementiert wurden, bevor Java zur Sprache hinzugefügt wurde. Das Programm kann verschiedene Arten von Paaren enthalten, z. B. Paar. Nach dem Löschen des Typs werden sie jedoch zum ursprünglichen Paartyp, und die ursprünglichen Typen sind alle Objekt.

Wenn die Typvariable begrenzt ist, wird der ursprüngliche Typ durch die erste begrenzende Typvariable ersetzt.

Wenn „Pair“ beispielsweise wie folgt deklariert wird:

public class Pair<T extends Comparable& Serializable> {
Nach dem Login kopieren

Dann ist der ursprüngliche Typ „Comparable“

Hinweis:

Wenn Pair wie diese Klasse als öffentlich deklariert wird Pair , wird der ursprüngliche Typ durch Serializable ersetzt und der Compiler fügt bei Bedarf eine Umwandlung in Comparable ein. Aus Effizienzgründen sollten getaggte Schnittstellen (d. h. Schnittstellen ohne Methoden) am Ende der durch Grenzen qualifizierten Liste platziert werden.

Um zwischen primitiven Typen und generischen Variablentypen zu unterscheiden

Beim Aufruf einer generischen Methode können Sie einen generischen Typ angeben oder nicht.

Ohne Angabe eines Generikums ist der Typ der generischen Variablen die niedrigste Ebene derselben übergeordneten Klasse mehrerer Typen in der Methode, bis Object.

Bei der Angabe eines Generikums müssen mehrere Typen in der Methode der generische Instanztyp oder seine Unterklasse sein.

public class Test{    
  public static void main(String[] args) {    
    /**不指定泛型的时候*/    
    int i=Test.add(1, 2); //这两个参数都是Integer,所以T为Integer类型    
    Number f=Test.add(1, 1.2);//这两个参数一个是Integer,以风格是Float,所以取同一父类的最小级,为Number    
    Object o=Test.add(1, "asd");//这两个参数一个是Integer,以风格是Float,所以取同一父类的最小级,为Object    
    
    /**指定泛型的时候*/    
    int a=Test.<Integer>add(1, 2);//指定了Integer,所以只能为Integer类型或者其子类    
    int b=Test.<Integer>add(1, 2.2);//编译错误,指定了Integer,不能为Float    
    Number c=Test.<Number>add(1, 2.2); //指定为Number,所以可以为Integer和Float    
  }    
  
  //这是一个简单的泛型方法    
  public static <T> T add(T x,T y){    
    return y;    
  }    
}
Nach dem Login kopieren

Tatsächlich ist es in einer generischen Klasse fast dasselbe, wenn der generische Typ nicht angegeben ist, außer dass der generische Typ zu diesem Zeitpunkt Object ist. Wenn beispielsweise in ArrayList der Wenn kein generischer Typ angegeben ist, kann jeder Objekttyp in ArrayList platziert werden.

4. C++-Vorlagenimplementierung

Obwohl ich C++ nicht verstehe, habe ich auch im Internet nach der Implementierung von C++ gesucht.

Das Erzeugen unterschiedlicher Typen für jede Instanziierung einer Vorlage in C++ ist ein Phänomen, das als „Aufblähen des Vorlagencodes“ bekannt ist.

Zum Beispiel vector, vector, vector werden hier insgesamt 3 verschiedene Vektorcodes generiert.



Weitere Artikel zu den Implementierungsprinzipien von Java-Generika 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