Generische Typen

Ein generischer Typ ist eine generische Klasse oder Schnittstelle, die über Typen parametrisiert wird. Die folgende Box-Klasse wird geändert, um das Konzept zu demonstrieren.

Eine einfache Box-Klasse

Untersuchen Sie zunächst eine nicht generische Box-Klasse, die mit Objekten eines beliebigen Typs arbeitet. Es müssen nur zwei Methoden bereitgestellt werden: set, das der Box ein Objekt hinzufügt, und get, das es abruft:

Da die Methoden ein Objekt akzeptieren oder zurückgeben, können Sie alles übergeben, was Sie möchten , vorausgesetzt, es ist nicht einer der primitiven Typen. Es gibt keine Möglichkeit, zur Kompilierungszeit zu überprüfen, wie die Klasse verwendet wird. Ein Teil des Codes platziert möglicherweise eine Ganzzahl in das Feld und erwartet, dass Ganzzahlen daraus entfernt werden, während ein anderer Teil des Codes fälschlicherweise einen String übergibt, was zu einem Laufzeitfehler führt.

Eine generische Version der Box-Klasse

Eine generische Klasse wird im folgenden Format definiert:

class name<T1, T2, ..., Tn> { /* ... */ }

Zum Aktualisieren der Box-Klasse Um Generika zu verwenden, erstellen Sie eine generische Typdeklaration, indem Sie den Code „public class Box“ in „public class Box < T > „. Dadurch wird die Typvariable T eingeführt, die überall in der Klasse verwendet werden kann.

Mit dieser Änderung wird die Box-Klasse zu:

Wie Sie sehen können, sind alle Vorkommen von Object Ersetzt durch T. Eine Typvariable kann ein beliebiger nicht primitiver Typ sein, den Sie angeben: ein beliebiger Klassentyp, ein beliebiger Schnittstellentyp, ein beliebiger Array-Typ oder sogar eine andere Typvariable.

Dieselbe Technik kann zum Erstellen angewendet werden Generische Schnittstellen.

Konventionen für die Benennung von Typparametern

Konventionell sind Typparameternamen einzelne Großbuchstaben. Dies steht in scharfem Kontrast zu den Konventionen zur Benennung von Variablen, die Sie bereits kennen, und das aus gutem Grund: Ohne diese Konvention wäre es schwierig, den Unterschied zwischen einer Typvariablen und einem normalen Klassen- oder Schnittstellennamen zu erkennen.

Die am häufigsten verwendeten Typparameternamen sind:

  • E-Element (wird häufig vom Java Collections Framework verwendet)
  • K-Key
  • N – Nummer
  • T – Typ
  • V – Wert
  • S, U, V usw. – 2., 3., 4. Typ

Diese Namen werden in der gesamten Java SE-API und im Rest dieser Lektion verwendet.

Aufrufen und Instanziieren eines generischen Typs

Verweisen auf die generische Box-Klasse Innerhalb Ihres Codes müssen Sie einen generischen Typaufruf ausführen, der T durch einen konkreten Wert ersetzt, z. B. Integer:

Box<Integer> integerBox;

Sie können sich einen generischen Typaufruf als ähnlich wie einen normalen Methodenaufruf vorstellen, aber anstatt ein Argument an am zu übergeben Nach dieser Methode übergeben Sie ein Typargument – in diesem Fall eine Ganzzahl – an die Box-Klasse selbst.

Terminologie für Typparameter und Typargumente: Viele Entwickler verwenden die Begriffe „Typparameter“ und „Typargument“ synonym. Diese Begriffe sind jedoch nicht dieselben. Beim Codieren werden Typargumente angegeben, um einen parametrisierten Typ zu erstellen. Daher ist das T in Foo < T > ein Typparameter und der String in Foo < String > f ist ein Typargument. In dieser Lektion wird diese Definition bei der Verwendung dieser Begriffe beachtet.

Wie jede andere Variablendeklaration erstellt dieser Code kein neues Box-Objekt. Es wird lediglich deklariert, dass integerBox einen Verweis auf eine „Box of Integer“ enthält. Auf diese Weise wird Box < Integer > gelesen.

Ein Aufruf eines generischen Typs wird allgemein als parametrisierter Typ bezeichnet.

Um diese Klasse zu instanziieren, verwenden Sie wie gewohnt das neue Schlüsselwort, setzen Sie jedoch < Ganzzahl > zwischen dem Klassennamen und der Klammer:

Box<Integer> integerBox = new Box<Integer>();

Der Diamant

In Java SE 7 und höher können Sie die zum Aufrufen des Konstruktors einer generischen Klasse erforderlichen Typargumente durch einen leeren Satz von Typargumenten ersetzen (< >), solange der Compiler die Typargumente aus dem Kontext ermitteln oder ableiten kann. Dieses Paar spitzer Klammern, < >, wird informell als Diamant bezeichnet. Beispielsweise können Sie eine Instanz von Box < Integer > mit der folgenden Anweisung erstellen:

Box<Integer> integerBox = new Box<>();

Weitere Informationen zur Diamantnotation und Typinferenz finden Sie unter Typinferenz.

Mehrere Typparameter

Wie bereits erwähnt, Eine generische Klasse kann mehrere Typparameter haben.Beispiel: Die generische OrderedPair-Klasse, die die generische Pair-Schnittstelle implementiert:

Die folgenden Anweisungen erstellen zwei Instanziierungen der OrderedPair-Klasse:

Der Code new OrderedPair < String, Integer >, instanziiert K als String und V als Integer. Daher sind die Parametertypen des OrderedPair-Konstruktors String bzw. Integer. Aufgrund von Autoboxing ist es gültig, einen String und ein Int an die Klasse zu übergeben.

Wie in The Diamond erwähnt, weil a Der Java-Compiler kann die K- und V-Typen aus der Deklaration OrderedPair < String, Integer > ableiten. Diese Anweisungen können mit Diamantnotation gekürzt werden:

OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8);OrderedPair<String, String> p2 = new OrderedPair<>("hello", "world");

Befolgen Sie zum Erstellen einer generischen Schnittstelle die gleichen Konventionen wie zum Erstellen einer generischen Klasse.

Parametrisierte Typen

OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));

Write a Comment

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.