Heim  >  Artikel  >  Java  >  Zusammenfassung der Verwendung von Generika und Reflexion - Generics

Zusammenfassung der Verwendung von Generika und Reflexion - Generics

高洛峰
高洛峰Original
2016-12-19 15:39:001616Durchsuche

Meiner Meinung nach ist JDK5.0 definitiv eine sehr bahnbrechende Version. In dieser Version werden viele wertvolle neue Funktionen bereitgestellt, und der Reflexionsmechanismus wurde verbessert 5.0 hat außerdem das bisherige Sammlungs-Framework umstrukturiert und generische Unterstützung hinzugefügt.
Seit der Veröffentlichung von 5.0 sind fast 10 Jahre vergangen. Über diesen Aspekt ist online und auch in Büchern viel Wissen verfügbar. Elephant schreibt diese Dinge jetzt, erstens, um seine eigenen Erfahrungen und Erfahrungen zusammenzufassen, und zweitens, in der Hoffnung, Kindern, die in diesem Bereich neu sind, etwas Hilfe zu geben.
Der größte Vorteil von Generika ist die Typprüfung, die besonders für Sammlungen nützlich ist. Sie ist auch beim Design des zugrunde liegenden Codes sehr nützlich, da sie die Wiederverwendung ermöglicht. Es gibt zwei Möglichkeiten, Generika zu definieren: Eine ist eine generische Klasse und die andere ist eine generische Methode.
Was genau sind Generika? Einfach ausgedrückt (vielleicht nicht streng) bedeutet dies, dass Typvariablen wie Typparameter verwendet werden. Unabhängig davon, ob es sich um eine Klasse, eine Schnittstelle oder eine Methode handelt, kann man sagen, dass Generika verwendet werden. Siehe Beispiel:
Generische Klasse
öffentliche Klasse Person setT(T t) {
This.t = t;
}
}
T ist eine Typvariable, bei der es sich um einen parametrisierten Typ handelt, der in spitzen Klammern (<>) eingeschlossen ist. Put es nach dem Klassennamen. Es können mehrere Typvariablen einer generischen Klasse definiert werden. Typvariablen werden im Allgemeinen durch einen Großbuchstaben dargestellt, wie z. B. Person in diesem Beispiel, List in JDK, Map usw.
Es ist möglich, eine generische Klasse zu instanziieren, indem die Typvariable durch eine konkrete Klasse ersetzt wird: Person person = new Person();
Es ist falsch, sie wie folgt zu instanziieren: Person(); //ERROR
Generische Methode


public getSqlSession() .selectOne(key, params);
}

Dies ist eine Methode, die ich in der MyBatisDao-Klasse im SSM3-Beispiel definiert habe. ist die Typvariable und das T vor get ist der Rückgabetyp. Tatsächlich weist diese Methode Probleme mit der Typsicherheit auf. Wenn ich diese Methode in RoleService aufrufe und den Rückgabetyp T als User schreibe, gibt der Compiler keine Warnmeldung aus.

Aber wenn ich es umschreibe und Generika zu MyBatisDao hinzufüge, erweitert die öffentliche Klasse MyBatisDao SqlSessionDaoSupport

Dann wird es einen Kompilierungsfehler im Rückgabetyp von User geben:

Basierend auf der Rollentypvariablen MyBatisDao schließt der Compiler, dass die darin definierte get-Methode den Rollentyp zurückgeben sollte. Nach dieser Änderung wird MyBatisDao jedoch zu einer generischen Klasse und die get-Methode ist keine generische Methode mehr. Können generische Methoden also Sicherheitsüberprüfungen durchführen? Ja, aber es erfordert einige Programmierkenntnisse. Der Schlüssel hängt mit der generischen Methode zusammen, die Sie später erwähnen.
Einschränkungen für Typparameter
Der durch Typvariablen wie dargestellte Bereich ist manchmal zu groß und manchmal ist die Verwendung unpraktisch. Jetzt müssen wir beispielsweise eine generische Klasse implementieren, die die Schnittstelle java.io.Serializable implementiert. Wie sollen wir das also tun? Um dieses Problem zu lösen, haben die JDK-Experten für uns einen sogenannten „eingeschränkten Wildcard-Typ“ entwickelt. Im Allgemeinen nennen wir sie Obergrenze und Untergrenze:
Obergrenze:
Untergrenze: > Fragezeichen (?) Wird als uneingeschränkter Platzhalter bezeichnet und kann jeden Typ darstellen. Manchmal ist die Verwendung von Typvariablen nicht so praktisch, und Platzhaltertypen lösen dieses Problem sehr gut.
bedeutet, dass T eine Klasse ist, die die Serializable-Schnittstelle implementiert, T ein Untertyp des Bindungstyps (Serializable) ist und T und der Bindungstyp eine Schnittstelle oder eine Klasse sein können. Wenn Sie eine Einschränkung hinzufügen möchten, die die Comparable-Schnittstelle implementiert, müssen Sie sie nur wie folgt schreiben: Diese Schreibweise ist etwas locker, da die Comparable-Schnittstelle eine generische Schnittstelle ist, die generische Parameter empfangen kann . Wir werden diese komplexe Situation jetzt nicht diskutieren.
Es kann verstanden werden, dass der Supertyp jeder T-Typ-Variable auch T selbst umfasst, da T als Supertyp von sich selbst betrachtet werden kann.
Warum heißt es dann, dass „extends“ die Obergrenze und „extends“ die untere Grenze ist? Aus den beiden vorherigen Erklärungen sollte ersichtlich sein, dass „extends Serializable“ oder „extens T“ darauf hinweist, dass die Typvariable eine Unterklasse von Serializable und ein Untertyp der T-Variablen sein muss. Ist dies gleichbedeutend mit einer Begrenzung der Obergrenze der Typvariablen? Auf die gleiche Weise können wir die Bedeutung der Untergrenze verstehen.
Nachdem wir so viel über Ober- und Untergrenzen gesagt haben, welchen Nutzen haben sie? und wie benutzt man es? Einfach ausgedrückt können durch Extends qualifizierte Typparameter aus generischen Objekten gelesen werden, und durch Super qualifizierte Typparameter können in generische Objekte geschrieben werden. Manche Kinder werden ohnmächtig, wenn sie das sagen.
Anders ausgedrückt: Eine Formel für die Ober- und Untergrenzen von Generika wurde zusammengefasst: PECS
PECS bedeutet Producer-Extends, Consumer-Super
Das Obige bedeutet, dass, wenn der parametrisierte Typ a darstellt Produzent Wenn es einen Verbraucher darstellt, verwenden Sie . Wenn es einen Verbraucher darstellt, verwenden Sie . Lassen Sie es uns zusammen mit der obigen Erklärung verstehen. Ist es klar? Wenn Sie es immer noch nicht ganz verstehen, fügt Elephant einen kurzen Code hinzu, um den Unterschied zu verstehen.
public void add(List list){
for(T t : list){
add(t);
}
}
public void add( T t){};
public void add(T t, List list){
list.add(t);
}
Generisches Löschen
Generika sind hauptsächlich Während der Kompilierung wird die Typsicherheit überprüft. Heutzutage werden zum Schreiben von Code im Allgemeinen Eclipse oder IntelliJ verwendet. Wenn ein Fehler auftritt, wird sofort eine rote Fehlermarkierung angezeigt. Wenn also ein Typkonvertierungsfehler auftritt, ist das Ergebnis offensichtlich. Während der Ausführungsphase des Programms erkennt die JVM jedoch nicht, dass Generika alle Klassen, Schnittstellen und Methoden mit Generika löschen und zu Rohtypen werden, d. h. Person< ;? erweitert die T>-Liste zur Listenliste usw.
Das Folgende ist das Ergebnis der Dekompilierung der vorherigen Person-Klasse mit Javap. Alle Typvariablen T wurden gelöscht. Da es sich bei T um einen unqualifizierten Typ handelt, wird er durch Object ersetzt. Darüber hinaus wurden in der Add-Methode entfernt.
öffentliche Klasse com.bolo.Person erweitert java.lang.Object{
private java.lang.Object t;
öffentliche com.bolo.Person();
öffentliche java.lang.Object getT ();
public void setT(java.lang.Object);
public void add(java.util.List);
public void add(java.lang.Object);
public void add(java.lang. Object, java.util.List);
}
Daher müssen wir für die Funktion des generischen Löschens auf die folgenden Punkte achten:
1. In der JVM gibt es keine Generics, nur gewöhnliche Klassen und Methoden.
2. Alle Typparameter werden durch qualifizierte Typen oder uneingeschränkte Typen mit Object ersetzt.
3. Bitte gehen Sie mit der Überladung von Methoden vorsichtig um. Durch die falsche Verwendung der Überladung wird nicht der gewünschte Polymorphismus erreicht.
4. Um die Typsicherheit zu gewährleisten, verwenden Sie bei Bedarf bitte die erzwungene Typkonvertierung.
Einschränkungen von Generika
Grundtypen können nicht als Typparameter verwendet werden. Person ist falsch, Sie können nur Person verwenden.
Bei der Typprüfung können nur primitive Typen verwendet werden. if(t Instanz von Person) Wenn es als if(t Instanz von Person) geschrieben wird, wird sofort ein Kompilierungsfehler angezeigt.
Die Typvariable kann nicht instanziiert werden. Es ist falsch, Folgendes zu schreiben: T t = new T()
Sie können kein Array parametrisierter Typen instanziieren. Person[] p = new Person[5] //ERROR
Statische Instanzvariablen und statische Methoden können nicht definiert werden. Wenn Sie so schreiben möchten: private static T a Dann tut es mir leid, der Compiler gibt Ihnen sofort eine Fehlermeldung.
Tatsächlich besteht kein Grund, über die Einschränkungen bei Generika zu sprechen. Solange Sie dies tun, wird Ihnen sofort ein Fehler angezeigt.
Schließlich sind Generika am nützlichsten für Sammlungen. Eine Sammlung ist ein Container, und Generika erleichtern die Wiederverwendung. Die Sammlung, die wir am häufigsten verwenden, ist die Liste, und der andere Container ist das Array. Elephant empfiehlt hier dringend, dass Sie häufiger Listen verwenden und versuchen, keine Arrays zu verwenden. Das erste ist, dass List über Typsicherheitsprüfungen verfügt, das zweite ist, dass List alle Funktionen von Arrays bereitstellt und umfangreicher ist, und das dritte ist, dass List GC optimiert. Wenn Sie Arrays verwenden, insbesondere Objektarrays bedienen, unerfahren sind und die Objektreferenzen im Array nicht freigeben, kann es leicht zu Speicherverlusten kommen.



Weitere allgemeine Artikel zur Zusammenfassung der Verwendung von Generika und Reflexion finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
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
Vorheriger Artikel:Java Generics – TyplöschungNächster Artikel:Java Generics – Typlöschung