Beispiel-Tutorial für Java-Generika – Generische Methode, Klasse, Schnittstelle
Java Genrics ist eine der wichtigsten Funktionen, die in Java 5 eingeführt wurden.
Wenn Sie an Java-Sammlungen mit Version 5 oder höher gearbeitet haben, sind Sie sicher, dass Sie sie verwendet haben.
Generika in Java mit Auflistungsklassen sind sehr einfach, bieten jedoch viel mehr Funktionen als nur das Erstellen der Art der Sammlung.
In diesem Artikel werden wir versuchen, die Funktionen von Generika kennenzulernen. Das Verstehen von Generika kann manchmal verwirrend werden, wenn wir Jargonwörter verwenden. Daher würde ich versuchen, es einfach und leicht verständlich zu halten.
Generika in Java
Generika wurden in Java 5 hinzugefügt, um die Überprüfung des Typs zur Kompilierungszeit und das Entfernen des Risikos von ClassCastException
zu ermöglichen, das während der Arbeit häufig auftrat mit Sammlungsklassen. Das gesamte Sammlungsframework wurde neu geschrieben, um Generika für die Typensicherheit zu verwenden. Lassen Sie uns sehen, wie Generika uns dabei helfen, Auflistungsklassen sicher zu verwenden.
Der obige Code wird einwandfrei kompiliert, löst jedoch zur Laufzeit ClassCastException aus, da wir versuchen, Object in der Liste in String umzuwandeln, während eines der Elemente vom Typ Integer ist. Nach Java 5 verwenden wir Sammlungsklassen wie die folgenden.
Beachten Sie, dass wir zum Zeitpunkt der Listenerstellung angegeben haben, dass der Elementtyp in der Liste String ist. Wenn wir also versuchen, einen anderen Objekttyp in die Liste aufzunehmen, gibt das Programm einen Fehler bei der Kompilierung aus. Beachten Sie auch, dass wir in der for-Schleife keine Typumwandlung des Elements in der Liste benötigen, wodurch die ClassCastException zur Laufzeit entfernt wird.
Generische Java-Klasse
Wir können unsere eigenen Klassen definieren mit Generika-Typ. Ein generischer Typ ist eine Klasse oder Schnittstelle, die über Typen parametrisiert wird. Wir verwenden spitze Klammern (< >), um den Typparameter anzugeben.
Um den Nutzen zu verstehen, sagen wir Wir haben eine einfache Klasse wie folgt:
Beachten Sie, dass wir bei Verwendung dieser Klasse Type Casting verwenden müssen und sie zur Laufzeit ClassCastException erzeugen kann. Jetzt verwenden wir die generische Java-Klasse, um dieselbe Klasse wie unten gezeigt neu zu schreiben.
Beachten Sie die Verwendung der GenericsType-Klasse in der Hauptmethode. Wir müssen kein Typ-Casting durchführen und können ClassCastException zur Laufzeit entfernen. Wenn der Typ zum Zeitpunkt der Erstellung nicht angegeben wird, gibt der Compiler eine Warnung aus, dass „GenericsType ein Rohtyp ist.
Verweise auf den generischen Typ GenericsType < T > sollte parametrisiert werden. „Wenn wir den Typ nicht angeben, wird der Typ zu Object
und erlaubt daher beide Zeichenfolgen und Integer-Objekte. Wir sollten jedoch immer versuchen, dies zu vermeiden, da wir bei der Arbeit an Rohtypen, die Laufzeitfehler verursachen können, Typumwandlung verwenden müssen.
Beachten Sie auch, dass es Java-Autoboxing unterstützt.
Java Generic Interface
Eine vergleichbare Schnittstelle ist ein großartiges Beispiel für Generics in Interfaces und lautet wie folgt:
Auf ähnliche Weise können wir generische Interfaces in Java erstellen haben mehrere Typparameter wie in der Kartenschnittstelle. A. Gain können wir auch einen parametrisierten Wert für einen parametrisierten Typ bereitstellen, z. B. new HashMap<String, List<String>>();
ist gültig.
Java Generic Type
Java Generic Type Naming Die Konvention hilft uns dabei, Code leicht zu verstehen, und eine Namenskonvention ist eine der besten Methoden der Java-Programmiersprache. Generika haben also auch eigene Namenskonventionen. Normalerweise sind Typparameternamen einzelne Großbuchstaben, damit sie leicht von Java-Variablen unterschieden werden können. Die am häufigsten verwendeten Typparameternamen sind:
- E – Element (wird vom Java Collections Framework häufig verwendet, z. B. ArrayList, Set usw.)
- K – Key ( In der Karte verwendet)
- N – Nummer
- T – Typ
- V – Wert (in der Karte verwendet)
- S, U, V usw. – 2., 3., 4. Typ
Generische Java-Methode
Manchmal möchten wir nicht, dass die gesamte Klasse parametrisiert wird. In diesem Fall können wir Erstellen Sie eine Java Generics-Methode. Da es sich bei dem Konstruktor um eine spezielle Methode handelt, können wir den Generika-Typ auch in Konstruktoren verwenden.
Hier ist eine Klasse, die ein Beispiel für eine generische Java-Methode zeigt.
Beachten Sie die isEqual-Methode Signatur mit Syntax zur Verwendung des generischen Typs in Methoden. Beachten Sie auch, wie diese Methoden in unserem Java-Programm verwendet werden. Wir können den Typ angeben, während wir diese Methoden aufrufen, oder wir können sie wie eine normale Methode aufrufen. Der Java-Compiler ist intelligent genug, um den Typ der zu verwendenden Variablen zu bestimmen. Diese Funktion wird als Typinferenz bezeichnet.
Java Generics Bounded Type Parameters
Angenommen, wir möchten den Objekttyp einschränken, der im parametrisierten Typ verwendet werden kann, z. B. in einer Methode, die zwei Objekte vergleicht, und wir möchten Stellen Sie sicher, dass die akzeptierten Objekte Comparables sind. Um einen begrenzten Typparameter zu deklarieren, listen Sie den Namen des Typparameters auf, gefolgt vom Schlüsselwort extens, gefolgt von seiner oberen Grenze, ähnlich wie bei der folgenden Methode.
Die Der Aufruf dieser Methoden ähnelt der unbegrenzten Methode, außer dass, wenn wir versuchen, eine Klasse zu verwenden, die nicht vergleichbar ist, ein Fehler bei der Kompilierung auftritt.
Begrenzte Typparameter können sowohl mit Methoden als auch verwendet werden Klassen und Schnittstellen.
Java Generics unterstützt auch mehrere Grenzen, dh < T erweitert A & B & C >. In diesem Fall kann A eine Schnittstelle oder Klasse sein. Wenn A Klasse ist, sollten B und C eine Schnittstelle sein. Wir können nicht mehr als eine Klasse in mehreren Grenzen haben.
Java-Generika und Vererbung
Das wissen wir Die Java-Vererbung ermöglicht es uns, eine Variable A einer anderen Variablen B zuzuweisen, wenn A eine Unterklasse von B ist. Wir könnten also denken, dass jeder generische Typ von A dem generischen Typ von B zugewiesen werden kann, aber dies ist nicht der Fall. Sehen wir uns das mit einem einfachen Programm an.
Wir dürfen MyClass keine MyClass < String > -Variable zuweisen < Objekt > Variable, da sie nicht miteinander verbunden sind, tatsächlich MyClass < T > Eltern ist Objekt.
Generische Java-Klassen und Subtypisierung
Wir können eine generische Klasse oder Schnittstelle subtypisieren, indem wir sie erweitern oder implementieren. Die Beziehung zwischen den Typparametern einer Klasse oder Schnittstelle und den Typparametern einer anderen Klasse wird durch die Extend- und Implementierungsklauseln bestimmt.
Die Subtypisierungsbeziehung bleibt erhalten, solange wir das Typargument nicht ändern. Das folgende Beispiel zeigt ein Beispiel für mehrere Typparameter.
Die Untertypen der Liste < String > kann MyList sein < Zeichenfolge, Objekt >, MyList < String, Integer > usw.
Java Generics-Platzhalter
Fragezeichen (?) Ist der Platzhalter in Generika und repräsentiert ein unbekannter Typ. Der Platzhalter kann als Typ eines Parameters, Felds oder einer lokalen Variablen und manchmal als Rückgabetyp verwendet werden. Wir können keine Platzhalter verwenden, während wir eine generische Methode aufrufen oder eine generische Klasse instanziieren. In den folgenden Abschnitten erfahren Sie mehr über Platzhalter mit oberen Grenzen, Platzhalter mit unteren Grenzen und Wildcard-Erfassung.
9.1) Java Generics Wildcard mit oberen Grenzen
Platzhalter mit oberen Grenzen werden zum Entspannen verwendet Einschränkung des Variablentyps in einer Methode. Angenommen, wir möchten eine Methode schreiben, die die Summe der Zahlen in der Liste zurückgibt, sodass unsere Implementierung ungefähr so aussieht.
Nun das Problem mit Die obige Implementierung funktioniert nicht mit List of Integers oder Doubles, da wir wissen, dass List < Integer > und List < Double > sind nicht verwandt. In diesem Fall ist ein Platzhalter mit oberen Grenzen hilfreich. Wir verwenden einen Platzhalter für Generika mit dem Schlüsselwort extensed und der Obergrenze oder Klasse oder Schnittstelle, mit der wir Argumente der Obergrenze oder ihrer Unterklassentypen übergeben können.
Die obige Implementierung kann wie das folgende Programm geändert werden. P. >
Es ist ähnlich wie beim Schreiben unseres Codes in Bezug auf die Schnittstelle. In der obigen Methode können wir alle Methoden der Obergrenzenklasse Number verwenden. Beachten Sie, dass wir mit einer Liste mit oberen Grenzen kein Objekt zur Liste hinzufügen dürfen, außer null. Wenn wir versuchen, der Liste innerhalb der Summenmethode ein Element hinzuzufügen, wird das Programm nicht kompiliert.
9.2) Java Generics Unbounded Wildcard
Manchmal haben wir eine Situation, in der wir Damit unsere generische Methode mit allen Typen funktioniert, kann in diesem Fall ein unbegrenzter Platzhalter verwendet werden. Es ist dasselbe wie mit <? erweitert Objekt >.
Wir können Liste < bereitstellen Zeichenfolge > oder List < Ganzzahl > oder eine andere Art von Objektlistenargument für die printData-Methode. Ähnlich wie bei der Liste der oberen Grenzen dürfen wir der Liste nichts hinzufügen.
9.3) Java Generics Wildcard mit niedrigerer Grenze
Angenommen, wir möchten einer Liste von Ganzzahlen in einer Methode Ganzzahlen hinzufügen, können wir den Argumenttyp als List < Integer beibehalten >, aber es wird mit Ganzzahlen verknüpft, während List < Number > und List < Objekt > kann auch Ganzzahlen enthalten, daher können wir einen Platzhalter mit niedrigerer Grenze verwenden, um dies zu erreichen. Wir verwenden einen generischen Platzhalter (?) Mit einem Super-Schlüsselwort und einer Klasse für die Untergrenze, um dies zu erreichen.
Wir können die Untergrenze oder einen beliebigen Supertyp der Untergrenze als Argument übergeben. In diesem Fall erlaubt der Java-Compiler das Hinzufügen einer Untergrenze gebundene Objekttypen an die Liste.
Subtypisierung mit Generics Wildcard
Java Generics Type Erasure
Generics in Java wurde hinzugefügt, um die Typprüfung zur Kompilierungszeit zu ermöglichen, und es wird zur Laufzeit nicht verwendet. Daher verwendet der Java-Compiler die Typlöschfunktion, um den gesamten generischen Typprüfungscode im Bytecode zu entfernen und bei Bedarf die Typumwandlung einzufügen. Durch das Löschen von Typen wird sichergestellt, dass für parametrisierte Typen keine neuen Klassen erstellt werden. Folglich verursachen Generika keinen Laufzeitaufwand.
Wenn wir beispielsweise eine generische Klasse wie die folgende haben:
Der Java-Compiler ersetzt den Parameter T für den begrenzten Typ durch die erste gebundene Schnittstelle Comparable , wie im folgenden Code beschrieben:
Häufig gestellte Fragen zu Generika
12.1) Warum verwenden wir Generika in Java?
Generika bieten eine starke Typprüfung zur Kompilierungszeit und verringern das Risiko von ClassCastException und explizites Casting von Objekten.
12.2) Was ist T in Generics?
Wir verwenden < T >, um eine generische Klasse, Schnittstelle und Methode zu erstellen. Das T wird bei der Verwendung durch den tatsächlichen Typ ersetzt.
12.3) Wie funktioniert Generics in Java?
Generischer Code gewährleistet die Typensicherheit. Der Compiler verwendet die Typlöschung, um alle Typparameter zur Kompilierungszeit zu entfernen und die Überlastung zur Laufzeit zu verringern.
Generika in Java – Weitere Lesungen
Das ist alles für Generika in Java, Java Generika sind ein sehr umfangreiches Thema und erfordern viel Zeit, um es zu verstehen und effektiv zu nutzen. Dieser Beitrag hier ist ein Versuch, grundlegende Details zu Generika bereitzustellen und wie wir damit unser Programm mit Typensicherheit erweitern können.