java generics tutorial with examples
Java-Generika sind eine Reihe von Funktionen, mit denen Sie Code unabhängig vom Datentyp schreiben können. In diesem Artikel werden Java-Generika anhand von Beispielen ausführlich erläutert:
Generika sind eine der wichtigsten Funktionen von Java und wurden ab Java 5 eingeführt.
Generika sind per Definition eine Reihe von Java-Sprachfunktionen, mit denen der Programmierer generische Typen und Funktionen verwenden und so die Typensicherheit gewährleisten kann.
Was du lernen wirst:
Wie funktionieren Generika in Java?
Wenn Sie bereits mit C ++ gearbeitet haben, entspricht Java Generics den Vorlagen in C ++. Mit Java Generics können Sie einen Parameter in Ihre Klassen- / Methodendefinition aufnehmen, der den Wert eines primitiven Datentyps hat.
Zum Beispiel, Sie können eine generische Klasse 'Array' wie folgt haben:
Klassenarray {….}
Wo ist der parametrisierte Typ?
Als Nächstes können Sie Objekte für diese Klasse wie folgt erstellen:
Array int_array = new Array () Array char_array = new Array ();
Bei einer generischen parametrisierten Klasse können Sie also Objekte derselben Klasse mit unterschiedlichen Datentypen als Parameter erstellen. Dies ist das Wesentliche bei der Verwendung von Java Generics.
Ebenso können Sie eine generische Methode mit einem parametrisierten Typ zum Sortieren eines Arrays schreiben und diese Methode dann für einen beliebigen primitiven Typ instanziieren.
Java-Generika werden hauptsächlich mit dem Sammlungsframework von Java verwendet. Die verschiedenen Sammlungen wie LinkedList, List, Map, HashMap usw. verwenden Generics zur Implementierung. Generika bieten Typensicherheit, da die Typprüfung zur Kompilierungszeit durchgeführt wird, wodurch Ihr Code stabiler wird.
Lassen Sie uns nun näher auf die Details der generischen Klassen und Methoden sowie auf andere verwandte Themen eingehen.
Generische Klassen
Eine generische Klasse ist dieselbe wie eine normale Klasse, außer dass auf den Klassennamen ein Typ in eckigen Klammern folgt.
Eine allgemeine Definition einer generischen Klasse lautet wie folgt:
Klasse Klassenname
{
Klassenvariablen;
… ..
Klassenmethoden;
}}
Sobald die Klasse definiert ist, können Sie Objekte eines beliebigen Datentyps wie folgt erstellen:
wie man in c ++ schläft
class_name obj = new class_name ();
Zum Beispiel, Für das Integer-Objekt lautet die Deklaration:
class_name obj = new class_name;
In ähnlicher Weise lautet das Objekt für den String-Datentyp:
class_name str_Obj = new class_name;
Eine Beispielimplementierung für die Generic-Klasse ist unten dargestellt.
class MyGenericClass { T obj; void add(T obj) { this.obj=obj; } T get() { return obj; } } class Main { public static void main(String args()) { MyGenericClass m_int=new MyGenericClass(); m_int.add(2); MyGenericClassmstr=new MyGenericClass(); mstr.add('SoftwaretestingHelp'); System.out.println('Member of MyGenericClass:' + m_int.get()); System.out.println('Member of MyGenericClass:' + mstr.get()); } }
Ausgabe:
Im obigen Programm ist eine Klasse MyGenericClass eine generische Klasse. Es gibt zwei Methoden, d. H. Addieren und Abrufen. Die Methode add initialisiert das generische Objekt, während die get-Methoden das Objekt zurückgeben.
In der Hauptfunktion deklarieren wir jeweils zwei Objekte vom Typ Integer und String. Wir initialisieren diese beiden Objekte mit ihren jeweiligen Anfangswerten mit der Methode add und geben dann den Inhalt dieser Objekte mit der Methode get aus.
Wir haben das Beispiel der generischen Klasse oben mit einem Typparameter vorgestellt. In der Realität kann eine Klasse jedoch auch mehr als einen Typparameter haben. In diesem Fall werden die Typparameter durch ein Komma getrennt.
Das folgende Beispiel zeigt dies:
classTest_Generics { T1 obj1; // An object of type T1 T2 obj2; // An object of type T2 // constructor to initialise T1 & T2 objects Test_Generics(T1 obj1, T2 obj2) { this.obj1 = obj1; this.obj2 = obj2; } public void print() { System.out.println('T1 Object:' + obj1); System.out.println('T2 Object:' + obj2); } } class Main { public static void main (String() args) { Test_Genericsobj = newTest_Generics('Java Generics', 1); obj.print(); } }
Ausgabe:
In diesem Programm haben wir zwei Typparameter, d. H. T1 und T2. Wir haben Funktionen zum Initialisieren der Mitgliedsobjekte und zum Drucken des Inhalts. In der Hauptfunktion deklarieren wir ein Objekt mit zwei Typen, d. H. String und Integer. Die Ausgabe des Programms zeigt den Inhalt des erstellten Objekts.
Genau wie Klassen können Sie auch generische Schnittstellen haben. Wir werden alles über Schnittstellen in einem separaten Thema erfahren.
Womit soll man XML-Dateien öffnen?
Java Generische Methoden
So wie Sie generische Klassen und Schnittstellen haben können, können Sie auch generische Methoden haben, falls Sie nicht eine ganze Klasse benötigen, um generisch zu sein.
Das folgende Programm zeigt die Implementierung der generischen Methode 'printGenericArray'. Beachten Sie den Methodenaufruf in der Hauptfunktion. Hier rufen wir die generische Methode zweimal auf, zuerst mit type und dann mit type.
public class Main{ public static void printGenericArray(T() items) { for ( T item : items){ System.out.print(item + ' '); } System.out.println(); } public static void main( String args() ) { Integer() int_Array = { 1, 3, 5, 7, 9, 11 }; Character() char_Array = { 'J', 'A', 'V', 'A', 'T','U','T','O','R','I','A', 'L','S' }; System.out.println( 'Integer Array contents:' ); printGenericArray(int_Array ); System.out.println( 'Character Array contents:' ); printGenericArray(char_Array ); } }
Ausgabe:
Begrenzte Typparameter
Begrenzte Typparameter werden angezeigt, wenn Sie die Datentypen in Generics einschränken möchten. Zum Beispiel, Wenn Sie möchten, dass eine bestimmte generische Klasse oder Methode oder eine Schnittstelle nur für numerische Datentypen funktioniert, können Sie dies mit dem Schlüsselwort 'extended' angeben.
Dies ist unten gezeigt:
List myList = new ArrayList(); List list1 = new ArrayList();
Die obigen zwei Deklarationen werden vom Compiler akzeptiert, da Long und Integer Unterklassen von Number sind.
Die nächste Erklärung wird jedoch ein Problem sein.
List list = new ArrayList();
Dies führt zu einem Fehler bei der Kompilierung, da String keine Zahl ist. Das Symbol '?' Im obigen Beispiel wird als Platzhalter bezeichnet und wird als Nächstes erläutert.
Daher werden im Allgemeinen begrenzte Typparameter verwendet, wenn Sie die Datentypen einschränken möchten, die in Ihrem generischen Code verwendet werden sollen.
Java Generics Wildcard
In Java wird ein Platzhalter durch ein Fragezeichen '?' Gekennzeichnet, mit dem auf einen unbekannten Typ verwiesen wird. Platzhalter werden meistens mit Generika als Parametertyp verwendet.
Wenn Sie generische Platzhalter verwenden, müssen Sie einen Punkt beachten: Obwohl das Objekt die Oberklasse aller anderen Klassen ist, die Sammlung von Objekten ( Zum Beispiel, Liste) ist keine Oberklasse aller anderen Sammlungen.
Abgesehen davon, dass Sie als Parametertyp verwendet werden, können Sie einen Platzhalter als Feld, als lokale Variable und als solche verwenden. Sie können jedoch niemals einen Platzhalter als Supertyp oder als Typargument verwenden, um eine generische Methode aufzurufen oder wenn eine Instanz einer generischen Klasse erstellt wird.
Es gibt viele Beispiele für mit Platzhaltern parametrisierte Typen (hier ist mindestens ein Typargument ein Platzhalter), wie unten gezeigt, und die an verschiedenen Stellen verwendeten Platzhalter werden unterschiedlich interpretiert:
- Sammlung <: Sammlung bezeichnet die gesamte Instanziierung der Sammlungsschnittstelle unabhängig vom verwendeten Typargument.
- Liste extends Number< : Liste repräsentiert alle Listentypen, bei denen der Elementtyp eine Zahl ist.
- Komparator: Alle Instanziierungen der Komparatorschnittstelle für Typargumente, die Stringsupertypes sind.
Beachten Sie, dass ein Wildcard-parametrisierter Typ eine Regel ist, die zum Erkennen gültiger Typen festgelegt wird. Es ist kein konkreter Datentyp. Generische Platzhalter können begrenzt oder unbegrenzt sein.
# 1) Ungebundene Platzhalter
In unbegrenzten Platzhaltern gibt es keine Einschränkungen für Typvariablen und wird wie folgt bezeichnet:
ArrayList mylist = new ArrayList(); ArrayList my_strList = new ArrayList();
# 2) Begrenzte Platzhalter
Wir haben bereits begrenzte Typen besprochen. Dadurch werden die Einschränkungen für den Datentyp festgelegt, der zum Instanziieren der Typparameter mithilfe der Schlüsselwörter 'erweitert' oder 'super' verwendet wird. Diese Platzhalter können weiter in Wildcards mit oberen und unteren Wildcards unterteilt werden.
- Upper Bounded Wildcards
Wenn Sie möchten, dass Ihr generischer Ausdruck für alle Unterklassen eines bestimmten Typs gültig ist, geben Sie den Upper Bounded Wildcard mit dem Schlüsselwort expand an.
Zum Beispiel, Angenommen, Sie benötigen eine generische Methode, die List, List usw. unterstützt, dann können Sie einen Upper Bounded Wildcard wie angeben Liste . Da Number eine Oberklasse ist, funktioniert diese generische Methode für alle ihre Unterklassen.
Das folgende Programm demonstriert dies.
importjava.util.*; public class Main { private static Number summation (List numbers){ double sum = 0.0; for (Number n : numbers) sum += n.doubleValue(); return sum; } public static void main(String() args) { //Number subtype : Integer Listint_list = Arrays.asList(1,3,5,7,9); System.out.println('Sum of the elements in int_list:' + summation(int_list)); //Number subtype : Double List doubles_list = Arrays.asList(1.0,1.5,2.0,2.5,3.0,3.5); System.out.println('Sum of the elements in doubles_list:' + summation(doubles_list)); } }
Ausgabe:
Hier haben wir einen Platzhalter für die obere Grenze, Liste, für das Typargument der Funktion 'Summation' bereitgestellt. In der Hauptfunktion definieren wir zwei Listen, d. H. Int_list vom Typ Integer und doubles_list vom Typ Double. Da Integer und Double die Unterklassen von Number sind, funktioniert die Funktionssummierung in beiden Listen einwandfrei.
- Lower Bounded Wildcards
Wenn der generische Ausdruck alle Oberklassen eines bestimmten Typs akzeptieren soll, können Sie für Ihr Typargument einen Platzhalter mit niedrigerer Grenze angeben.
Eine beispielhafte Implementierung hierfür ist unten angegeben:
importjava.util.*; class Main { public static void main(String() args) { //Integer List ListInt_list= Arrays.asList(1,3,5,7); System.out.print('Integer List:'); printforLowerBoundedWildcards(Int_list); //Number list ListNumber_list= Arrays.asList(2,4,6,8); System.out.print('Number List:'); printforLowerBoundedWildcards(Number_list); } public static void printforLowerBoundedWildcards(List list) { System.out.println(list); } }
Ausgabe:
In diesem Programm lautet der angegebene Platzhalter für die untere Grenze 'Liste'. Dann haben wir in der Hauptfunktion eine Typliste und die Liste. Da wir den Lower Bounded Wildcard verwendet haben, ist die Number-Klasse eine Oberklasse von Integer, einem gültigen Typargument.
Vorteile von Java Generics
# 1) Typensicherheit
Generika sorgen für Typensicherheit. Dies bedeutet, dass die Typprüfung eher zur Kompilierungszeit als zur Laufzeit erfolgt. Daher besteht keine Chance, dass zur Laufzeit 'ClassCastException' angezeigt wird, da die richtigen Typen verwendet werden.
importjava.util.*; class Main { public static void main(String() args) { List mylist = new ArrayList(); mylist.add(10); mylist.add('10'); System.out.println(mylist); List list = new ArrayList(); list.add(10); list.add('10');// compile-time error System.out.println(list); } }
Im obigen Programm haben wir zwei Listen, eine ohne Generika und eine mit Generika. In der nicht generischen Liste gibt es keine Typensicherheit. Sie können eine Ganzzahl, eine Zeichenfolge usw. als Element hinzufügen, und diese wird akzeptiert.
In der generischen Liste können Sie nur einen Elementtyp hinzufügen, der im generischen Ausdruck angegeben ist. Wenn Sie versuchen, ein Element eines anderen Typs hinzuzufügen, führt dies zu einem Fehler bei der Kompilierung.
Im obigen Programm blinkt der Fehler bei der Kompilierung in der Zeile:
list.add('10');
# 2) Wiederverwendbarkeit von Code
Mit Generics müssen Sie nicht für jeden Datentyp einen eigenen Code schreiben. Sie können eine einzelne Klasse oder Methode usw. schreiben und für alle Datentypen verwenden.
# 3) Keine Notwendigkeit für Typografie
Da Sie Generics verwenden, kennt der Compiler die verwendeten Typen, sodass keine Typumwandlung erforderlich ist.
Betrachten Sie den folgenden Code:
List mylist = new ArrayList(); mylist.add('Java'); String mystr = (String) list.get(0); //typecasting required
Wie Sie sehen können, wenn eine normale Liste verwendet wird, müssen Sie das Listenelement auf die entsprechende Weise typisieren, wie es für das obige mystr gemacht wird.
Schreiben wir nun den gleichen Code noch einmal mit einer generischen Liste.
List list = new ArrayList(); list.add('Java'); String mystr = list.get(0);
Hier haben wir den Zeichenfolgentyp als generischen Ausdruck für die Listendeklaration angegeben. Um einzelne Elemente dieser Liste abzurufen, müssen wir daher keine Typumwandlung durchführen.
# 4) Implementieren Sie generische Algorithmen
Sie können viel mehr generische Algorithmen implementieren, wenn Sie Generics zum Codieren verwenden.
Fragen und Antworten zum Selen-Interview für 4 Jahre Erfahrung
# 5) Überprüfung der Kompilierungszeit
Wie bereits erwähnt, überprüft der Compiler bei Verwendung von Generics in Ihrem Java-Programm die Typen zur Kompilierungszeit und verhindert so ein abnormales Beenden des Programms zur Laufzeit.
Häufig gestellte Fragen
F # 1) Warum verwenden wir Generika in Java?
Antworten: Generika stellen die Typunabhängigkeit sicher, d. H. Wir können einen Typparameter bereitstellen, während wir eine Klasse / Schnittstelle / Methode usw. definieren, damit wir während der tatsächlichen Instanziierung den tatsächlichen Typ angeben können. Auf diese Weise bieten wir auch die Wiederverwendbarkeit von Code.
F # 2) Sind Generika in Java wichtig?
Antworten: Ja. In der Tat sind Generika die wichtigsten Funktionen von Java, um die Typensicherheit zu gewährleisten, d. H. Die Typprüfung zur Kompilierungszeit.
F # 3) Wann hat Java Generics hinzugefügt?
Antworten: Generics wurden Java 2004 mit J2SE 5.0 hinzugefügt, um die Sicherheit des Typs zur Kompilierungszeit in Java zu gewährleisten.
F # 4) Was ist ein generischer Typ?
Antworten: Ein generischer Typ ist eine generische Klasse, Schnittstelle oder Methode, die mit einem Typparameter versehen ist. Dies ermöglicht Typensicherheit und Wiederverwendung von Code.
F # 5) Können wir Generics mit Array in Java verwenden?
Antworten: Nein. Java erlaubt keine generischen Arrays.
Fazit
Damit ist das Tutorial zu Java-Generika abgeschlossen, das als eine der wichtigsten Funktionen in neueren Java-Versionen angesehen wird. Die Verwendung von Generics in Java-Programmen gewährleistet die Typensicherheit sowie die Wiederverwendung von Code. Außerdem wird die Überprüfung der Kompilierungszeit sichergestellt, damit das Programm zur Laufzeit nicht unterbrochen wird.
Java-Generika sind vor allem mit der Java-Sammlungsoberfläche nützlich, die wir in einem anderen Tutorial in dieser Reihe ausführlich behandeln werden.
Fröhliches Lesen!!
Literatur-Empfehlungen
- 15 besten JAVA-Tools für Entwicklung, Erstellung, Profiler, Codeabdeckung und Überprüfung
- JCF-Tutorial (Java Collections Framework)
- Java DataTypes, Loops, Arrays, Switch und Assertions
- Java-Bereitstellung: Erstellung und Ausführung einer Java-JAR-Datei
- Java-Ausnahmen und Ausnahmebehandlung mit Beispielen
- JAVA-Tutorial für Anfänger: Über 100 praktische Java-Video-Tutorials
- Java Reflection Tutorial mit Beispielen
- Java 'this' Schlüsselwort: Tutorial mit Codebeispielen