Heim  >  Artikel  >  Java  >  Java – Generika

Java – Generika

巴扎黑
巴扎黑Original
2017-06-27 09:13:571821Durchsuche

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.

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

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 Applef7e83be87db5cd2d9a8a0b8117b38cd4{}

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 MyClass8742468051c85b06f0a0af9e3e506b5c 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 MyClassf7e83be87db5cd2d9a8a0b8117b38cd4 oder new MyClassc0f559cc8d56b43654fcbe4aa9df7b4a 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:

MyClassf7e83be87db5cd2d9a8a0b8117b38cd4 class1 = new MyClassf7e83be87db5cd2d9a8a0b8117b38cd4();

MyClassc0f559cc8d56b43654fcbe4aa9df7b4a 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. G4ee996100bf04ab273e687539c860625 ist kein Untertyp von Gad40e550a33cb99ea30eede96e03e60e.

Angenommen, Lista87fdacec66f0909fc0757c19f2d2b1d kann logischerweise als übergeordnete Klasse von Listf7e83be87db5cd2d9a8a0b8117b38cd4 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 Listf7e83be87db5cd2d9a8a0b8117b38cd4

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 List6b3d0130bba23ae47fe2b8e8cddf0195 ist logischerweise die übergeordnete Klasse von Listc0f559cc8d56b43654fcbe4aa9df7b4a, Lista106241f68edc629be816c498f304ade... und allen tatsächlichen Parametern vom Typ Listb8eff36bbb42b608e3cc5aaf9728ac04. 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 Listc13078eef089064b7e80988f58350b9c kein Untertyp von List5c58ee79afe736c10ab537fb5aaf549d 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

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 cf0999ba5f96e04830f53339e5089ca9 a, Sammlung8742468051c85b06f0a0af9e3e506b5c 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 Listd94943c0b4933ad8cac500132f64757f erscheint der Typparameter V in den Signaturen von Methoden wie get(), add(), contains() usw. Wenn Sie eine Variable vom Typ Mapb56561a2c0bc639cf0044c0859afb88f 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 8742468051c85b06f0a0af9e3e506b5c >}

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 Matrixb873a6c8c13b900ce46a9356e963df29 ;Float>-Typ, aber wenn Sie versuchen, eine Variable vom Typ Matrixf7e83be87db5cd2d9a8a0b8117b38cd4 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 Liste6b3d0130bba23ae47fe2b8e8cddf0195 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 List30690cee1a11d5dfbdced93b89f678ee-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

8742468051c85b06f0a0af9e3e506b5c T[] makeArray(Collection8742468051c85b06f0a0af9e3e506b5c 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!

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