Heim > Java > javaLernprogramm > Hauptteil

Java – Generika

巴扎黑
Freigeben: 2017-06-27 09:13:57
Original
1869 Leute haben es durchsucht

Typparameter

wird verwendet, wenn eine generische-Klasse definiert oder eine Variable einer generischen-Klasse deklariert wird Spitze Klammern zur Angabe formaler Typparameter. Die Beziehung zwischen formalen Typparametern und tatsächlichen Typparametern ähnelt der Beziehung zwischen formalen Methodenparametern und tatsächlichen Methodenparametern, mit der Ausnahme, dass Typparameter eher Typen als Werte darstellen.

Benannte Typparameter

Die empfohlene Namenskonvention besteht darin, für Typparameter großgeschriebene, aus einem Buchstaben bestehende Namen zu verwenden. Dies unterscheidet sich von der C++-Konvention (siehe Anhang A: Vergleich mit C++-Vorlagen) und spiegelt die Annahme wider, dass die meisten generischen-Klassen über eine kleine Anzahl von Typparametern verfügen. Für das allgemeine generische-Muster lautet der empfohlene Name:

K – Schlüssel, beispielsweise ein zugeordneter Schlüssel.
V – Wert, z. B. der Inhalt von List und Set oder der Wert in Map.
E ——Ausnahmeklasse.
T —— Generisch.

方法签名由方法名称和一个参数列表(方法的参数的顺序和类型)组成。
Nach dem Login kopieren

1. Warum Generika verwenden

1. Es gibt keine Begrenzung für die Elemente, die eingefügt werden können. Das Einfügen von zwei verschiedenen Objekten kann zu Ausnahmen führen.

2. Werfen Sie das Objekt in die Sammlung. Die Sammlung verliert nur die Statusinformationen des Objekts, also nach dem Herausnehmen Bei den Sammlungselementen ist normalerweise auch eine erzwungene Konvertierung erforderlich

2. Was sind Generika

Die parametrisierten Typen von Java werden Generika genannt, die es dem Programm ermöglichen, beim Erstellen einer Sammlung den Typ der Sammlungselemente anzugeben

3. Auf die generische Rautensyntax

muss nur ein Paar Rautenklammern folgen, keine Notwendigkeit für Generika

4. Erstellen Sie eine benutzerdefinierte Klasse mit einer generischen Deklaration. Wenn Sie einen Konstruktor für die Klasse definieren, sollte der Konstruktorname weiterhin der ursprüngliche Klassenname sein .

5. Leiten Sie eine Unterklasse von einer generischen Klasse ab. Beim Erben müssen Sie die tatsächlichen Parameter für die übergeordnete Klasse übergeben

öffentliche Klasse A erweitert Apple{}

Alle Methoden, die die übergeordnete Klasse überschreiben, werden zum entsprechenden Typ

Sie können auch keine tatsächlichen Parameter übergeben

public class A erweitert Apple{}

Wird als Objekttyp behandelt

Es gibt keine generische Klasse

Unabhängig von den tatsächlichen Typparametern eines Generikums haben sie zur Laufzeit immer dieselbe Klasse. Unabhängig davon, welcher Typ tatsächlicher Parameter an den generischen Typparameter übergeben wird, ( liegt im Zweck des Konzepts der Generika in Java, das dazu führt, dass es nur in der Codekompilierungsphase wirkt. Während des Kompilierungsprozesses , Nachdem das generische Ergebnis korrekt überprüft wurde, werden die relevanten Informationen des Generikums gelöscht, das heißt, die erfolgreich kompilierte Klassendatei enthält keine generischen Informationen und die generischen Informationen gelangen nicht in die Laufzeitphase .) Für Java werden sie immer noch als dieselbe Klasse behandelt und belegen einen Speicherplatz im Speicher. Daher dürfen Typen nicht bei der Deklaration und Initialisierung von statischen Methoden, statischen Initialisierungsblöcken oder statischen Variablen verwendet werden Parameter

                                                                         

Statische Variablen werden von allen Instanzen einer generischen Klasse gemeinsam genutzt. Für eine als MyClass deklarierte Klasse ist die Methode für den Zugriff auf die darin enthaltenen statischen Variablen immer noch MyClass.myStaticVar. Unabhängig davon, ob die Objekte über new MyClass oder new MyClass erstellt werden, teilen sie sich alle eine statische Variable. Gehen Sie davon aus, dass Typparameter als Typen statischer Variablen zulässig sind. Dann stellen Sie sich folgende Situation vor:

MyClass class1 = new MyClass();

MyClass class2 = new MyClass< ;Integer>();

class1.myStaticVar = "hello";

class2.myStaticVar = 5;

Aufgrund der Typlöschung des Generikums System Außer (Typ Löschung). myStaticVar wird auf den Objekttyp zurückgesetzt, und wenn class1.myStaticVar= "hello"; aufgerufen wird, führt der Compiler eine erzwungene Typkonvertierung durch, d. h. myStaticVar = (String)"hello"; aufgerufen, führt der Compiler weiterhin die erzwungene Typkonvertierung durch, myStaticVar = (Integer)Integer.valueOf(5); Zu diesem Zeitpunkt ist myStaticVar natürlich vom Typ String, also gibt es eine Typsicherheitsproblem. Daher erlaubt das generische System nicht, dass statische Variablen einer Klasse Typparameter als Variablentypen verwenden.

Generische Klassen werden nicht tatsächlich im System generiert, daher kann die generische Klasse nicht nach dem Instanzod-Operator verwendet werden, da sie überhaupt nicht existiert!

7. Geben Sie Platzhalter ein

Beachten Sie Folgendes: Wenn Foo ist ein Untertyp von Bar und G ist eine Klasse oder Schnittstelle mit einer generischen Deklaration. G ist kein Untertyp von G.

Angenommen, List kann logischerweise als übergeordnete Klasse von List betrachtet werden, dann weist a.test(list) keinen Fehler auf message , dann stellt sich die Frage: Welcher Art sind die Daten, wenn sie über die Methode getData() abgerufen werden? Ganzzahl? Float? Und aufgrund der unkontrollierbaren Reihenfolge im Programmierprozess müssen bei Bedarf Typbeurteilungen und erzwungene Typkonvertierungen durchgeführt werden. Dies widerspricht offensichtlich dem Konzept der Generika. Daher kann logischerweise nicht als übergeordnete Klasse von List

Um die übergeordnete Klasse verschiedener generischer Sammlungen darzustellen, können Sie Typ-Platzhalter verwenden, bei denen es sich um ein Fragezeichen handelt. Es kann mit jedem Typ übereinstimmen:

Typ-Wildcards werden im Allgemeinen anstelle spezifischer tatsächlicher Typparameter verwendet? Beachten Sie, dass es sich hier um tatsächliche Typparameter handelt, nicht um Typparameter! Und List ist logischerweise die übergeordnete Klasse von List, List

>... und allen tatsächlichen Parametern vom Typ List. Daraus können wir immer noch generische Methoden definieren, um solche Anforderungen zu erfüllen.

Unabhängig vom tatsächlichen Typ der Liste enthält sie ein Objekt

Hinweis: Nur mit Platzhaltern bedeutet Es ist die übergeordnete Klasse verschiedener generischer Sammlungen und kann ihr keine Elemente hinzufügen

kennt den Typ der Elemente in der C-Sammlung nicht und kann ihr keine Objekte hinzufügen

7.1 Legen Sie die Obergrenze für Platzhalter fest

Da List kein Untertyp von List ist, tritt ein Kompilierungsfehler auf

Dies kann recycelt werden. Verwenden Sie eingeschränkte generische Platzhalter

7.2 Legen Sie die Obergrenze der Typparameter fest

8. Generische Methoden

Klasse definieren, Typparameter werden in der Schnittstelle nicht verwendet. Beim Definieren von Methoden möchte ich gleichzeitig

unabhängige generische statische Methoden definieren, ohne Multi zu berücksichtigen -Threading. Es wird nur einmal initialisiert und aufgerufen, es kommt nicht zu überlappenden Initialisierungen und falschen Aufrufen und es kommt nicht zu Situationen wie dem Lesen fehlerhafter Daten in der Datenbank, sodass bei der erzwungenen Typkonvertierung keine Codefehler auftreten.

Die in der Methodendeklaration definierten Formalparameter können nur in dieser Methode verwendet werden.

Im Gegensatz zu Klassen und Schnittstellen müssen Generika in Methoden nicht die tatsächlich übergebenen Typparameter anzeigen

Der Compiler darf sich nicht darüber im Klaren sein, für welchen Typ Sie übergeben werden

Für Beispiel: test a, Collection b>

Wenn Sie einen String-Typ oder einen Objekttyp übergeben, weiß der Compiler nicht, um welchen Typ es sich bei Ihrem T handelt

Kann es in a, Sammlung b>

Abschnitt „Generische Methode“ Sie haben gesehen, dass Sie eine Klasse generisch machen können, indem Sie ihrer Definition eine Liste formaler Typparameter hinzufügen. Methoden können auch generisch sein, unabhängig davon, ob die Klasse, in der sie definiert sind, generisch ist oder nicht.

Generische Klassen erzwingen Typeinschränkungen über mehrere Methodensignaturen hinweg. In List erscheint der Typparameter V in den Signaturen von Methoden wie get(), add(), contains() usw. Wenn Sie eine Variable vom Typ Map erstellen, deklarieren Sie eine Typbeschränkung zwischen Methoden. Der Wert, den Sie an add() übergeben, ist vom gleichen Typ wie der von get() zurückgegebene Wert.

In ähnlicher Weise wird eine generische Methode im Allgemeinen deklariert, weil Sie eine Typbeschränkung für mehrere Parameter der Methode deklarieren möchten. Beispielsweise gibt die ifThenElse()-Methode im folgenden Code abhängig vom booleschen Wert ihres ersten Parameters entweder den zweiten oder den dritten Parameter zurück:

public >}

Beachten Sie, dass Sie ifThenElse() aufrufen können, ohne dem Compiler explizit mitzuteilen, was Sie für den T-Wert wünschen. Dem Compiler muss nicht explizit mitgeteilt werden, welche Werte T haben wird; er weiß lediglich, dass die Werte alle gleich sein müssen. Mit dem Compiler können Sie den folgenden Code aufrufen, da der Compiler mithilfe der Typinferenz ableiten kann, dass der durch T ersetzte String alle Typeinschränkungen erfüllt:
String s = ifThenElse(b, "a", "b");

In ähnlicher Weise können Sie Folgendes aufrufen:

Integer i = ifThenElse(b, new Integer(1), new Integer(2));

Allerdings Kompilierung Der folgende Code wird vom Compiler nicht zugelassen, da kein Typ die erforderlichen Typeinschränkungen erfüllen würde:

String s = ifThenElse(b, "pi", new Float ( 3.14));

Warum haben Sie sich für die Verwendung einer generischen Methode entschieden, anstatt Typ T zur Klassendefinition hinzuzufügen? Es gibt (mindestens) zwei Fälle, in denen dies getan werden sollte:

Wenn eine generische Methode statisch ist, können Klassentypparameter in diesem Fall nicht verwendet werden.

Wenn eine Typbeschränkung für T wirklich lokal für eine Methode ist, bedeutet dies, dass derselbe Typ T in einer anderen Methodensignatur desselben nicht verwendet wird Klassenbeschränkung. Die Signatur eines geschlossenen Typs kann vereinfacht werden, indem die Typparameter einer generischen Methode lokal für die Methode festgelegt werden.


Eingeschränkter Typ

Generische Methode im vorherigen Bildschirm Im Beispiel , der Typparameter V ist ein uneingeschränkter oder uneingeschränkter Typ. Manchmal ist es erforderlich, zusätzliche Einschränkungen für Typparameter anzugeben, wenn die Typparameter nicht vollständig angegeben wurden.

Betrachten Sie die Beispielklasse „Matrix“, die einen Typparameter V verwendet, der durch die Klasse „Number“ begrenzt ist:

öffentliche Klasse Matrix ;Float>-Typ, aber wenn Sie versuchen, eine Variable vom Typ Matrix zu definieren, tritt ein Fehler auf. Der Typparameter V wird als durch Number begrenzt ausgewertet. Wenn keine Typbeschränkungen vorliegen, wird davon ausgegangen, dass Typparameter durch Object eingeschränkt werden. Aus diesem Grund ermöglicht das Beispiel im vorherigen Bildschirm, Generische Methoden, dass List.get() ein Objekt zurückgibt, wenn es für eine Liste aufgerufen wird, auch wenn der Compiler den Typ des Typparameters V nicht kennt.

9. Der Unterschied zwischen generischen Methoden und Typ-Wildcards

Wenn eine Methode vom Typ ist Wenn der formale Parameter (a) oder der Typ des Rückgabewerts vom Typ eines anderen formalen Parameters (b) abhängt, sollten in der Typdeklaration des formalen Parameters (b) keine Platzhalter verwendet werden. In der Methodensignatur können nur Typparameter deklariert werden. , also eine generische Methode.

Was ich verstehe, ist, dass der Typ-Platzhalter keine Elemente in der Sammlung hinzufügen oder ändern muss und an andere angehängt wird, anstatt an andere, die an ihn angehängt sind.

Typplatzhalter können verwendet werden, um den Typ formaler Parameter in Methodensignaturen zu definieren oder um die Typen von Variablen zu definieren. Typparameter müssen in der entsprechenden Methode explizit deklariert werden.

10. Löschen und Konvertieren

Beim Zuweisen eines Objekts mit generischen Informationen zu einem anderen. Beim Hinzufügen eines Variable ohne generische Informationen, alle Typinformationen in spitzen Klammern werden verworfen.

Beim Zuweisen von li zur Liste löscht der Compiler das Die allgemeinen Informationen des ersteren gehen verloren, d. h. die Typinformationen der Elemente in der Listensammlung gehen verloren. Java erlaubt auch die direkte Zuweisung des Listenobjekts zu einer List-Variablen, sodass das Programm kompiliert und übergeben werden kann, gibt aber nur

„ungeprüfte Konvertierung“ aus (Änderung der logischen Die übergeordnete Klasse ist der Unterklasse direkt zugeordnet)

, aber die Listenvariable bezieht sich tatsächlich auf die Auflistung list. Wenn also versucht wird, die Elemente in der Auflistung als Objekt vom Typ String herauszunehmen, wird ein ausgelöst run Exception

11. Generics und Arrays

Java-Generika haben ein sehr wichtiges Designprinzip: Wenn ein Code beim Kompilieren keine Warnung „nicht konvertiert“ auslöst, verursacht das Programm keine ClassCastException-Ausnahme. Der Typ aller Array-Elemente darf keine Typvariablen oder Typparameter enthalten, es sei denn, es handelt sich um einen unbegrenzten Typplatzhalter. Der Elementtyp kann jedoch so deklariert werden, dass er ein Array von Typvariablen oder Typparametern enthält

Angenommen, es kann passieren, wird keine Warnung, sondern eine Ausnahme ausgelöst

Ändern Sie es in das folgende Format:

Die erste Zeile enthält eine Warnung „ungeprüfte Konvertierung“ und die letzte Zeile löst auch eine Ausnahme aus

Unbegrenzte Platzhalter erstellen Generisches Array

gibt beim Kompilieren keine Warnung aus, aber zur Laufzeit wird eine Ausnahme ausgelöst, da das Programm das erste Sammlungselement des erzwingen muss erstes Array-Element von lsa In String-Typ konvertieren, daher sollte das Programm den Instanzenoperator verwenden, um seinen Datentyp sicherzustellen

Ähnlich wird ein Array-Objekt erstellt, dessen Elementtyp ein Typ ist Variable verursacht auch einen Kompilierungsfehler

T[] makeArray(Collection coll)

{ return new T[cool.size()]

}

Die Typvariable existiert zur Laufzeit nicht und der Compiler kann den tatsächlichen Typ nicht ermitteln

Das obige ist der detaillierte Inhalt vonJava – Generika. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen 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