Generika bedeutet parametrisierte Typen . Die Idee besteht darin, Typen (Integer, String usw. und benutzerdefinierte Typen) als Parameter für Methoden, Klassen und Schnittstellen zuzulassen. Mithilfe von Generics ist es möglich, Klassen zu erstellen, die mit unterschiedlichen Datentypen arbeiten. Eine Entität wie eine Klasse, eine Schnittstelle oder eine Methode, die mit einem parametrisierten Typ arbeitet, ist eine generische Entität.
Warum Generika?
Der Objekt ist die Oberklasse aller anderen Klassen und die Objektreferenz kann auf jedes Objekt verweisen. Diesen Funktionen mangelt es an Typsicherheit. Generics fügen diese Art von Sicherheitsfunktion hinzu. Wir werden diese Art von Sicherheitsfunktion in späteren Beispielen besprechen.
Generika in Java ähneln Vorlagen in C++. Klassen wie HashSet, ArrayList, HashMap usw. verwenden beispielsweise sehr gut Generika. Es gibt einige grundlegende Unterschiede zwischen den beiden Ansätzen für generische Typen.
Arten von Java-Generika
Generische Methode: Eine generische Java-Methode verwendet einen Parameter und gibt einen Wert zurück, nachdem eine Aufgabe ausgeführt wurde. Es ist genau wie eine normale Funktion, allerdings verfügt eine generische Methode über Typparameter, die nach dem tatsächlichen Typ angegeben werden. Dadurch kann die generische Methode allgemeiner genutzt werden. Der Compiler sorgt für die Art der Sicherheit, die es Programmierern ermöglicht, einfach zu programmieren, da sie keine langen, individuellen Typumwandlungen durchführen müssen.
Generische Klassen: Eine generische Klasse wird genauso implementiert wie eine nicht generische Klasse. Der einzige Unterschied besteht darin, dass es einen Typparameterabschnitt enthält. Es kann mehr als einen Parametertyp geben, getrennt durch ein Komma. Die Klassen, die einen oder mehrere Parameter akzeptieren, werden als parametrisierte Klassen oder parametrisierte Typen bezeichnet.
Generische Klasse
Wie C++ verwenden wir es, um Parametertypen bei der Erstellung generischer Klassen anzugeben. Um Objekte einer generischen Klasse zu erstellen, verwenden wir die folgende Syntax.
// To create an instance of generic class BaseType obj = new BaseType ()>
Notiz: Im Parametertyp können wir keine Grundelemente wie „int“, „char“ oder „double“ verwenden.
Java
// Java program to show working of user defined> // Generic classes> // We use to specify Parameter type> class> Test {> > // An object of type T is declared> > T obj;> > Test(T obj) {> this> .obj = obj; }> // constructor> > public> T getObject() {> return> this> .obj; }> }> // Driver class to test above> class> Main {> > public> static> void> main(String[] args)> > {> > // instance of Integer type> > Test iObj => new> Test(> 15> );> > System.out.println(iObj.getObject());> > // instance of String type> > Test sObj> > => new> Test(> 'GeeksForGeeks'> );> > System.out.println(sObj.getObject());> > }> }> |
>
>Ausgabe
15 GeeksForGeeks>
Wir können auch mehrere Typparameter in generischen Klassen übergeben.
Java
auswählen als
// Java program to show multiple> // type parameters in Java Generics> // We use to specify Parameter type> class> Test> {> > T obj1;> // An object of type T> > U obj2;> // An object of type U> > // constructor> > Test(T obj1, U obj2)> > {> > this> .obj1 = obj1;> > this> .obj2 = obj2;> > }> > // To print objects of T and U> > public> void> print()> > {> > System.out.println(obj1);> > System.out.println(obj2);> > }> }> // Driver class to test above> class> Main> {> > public> static> void> main (String[] args)> > {> > Test obj => > new> Test(> 'GfG'> ,> 15> );> > obj.print();> > }> }> |
>
>Ausgabe
GfG 15>
Allgemeine Funktionen:
Wir können auch generische Funktionen schreiben, die mit unterschiedlichen Argumenttypen aufgerufen werden können, basierend auf dem Typ der Argumente, die an die generische Methode übergeben werden. Der Compiler verarbeitet jede Methode.
Java
zu einem Array in Java hinzufügen
// Java program to show working of user defined> // Generic functions> class> Test {> > // A Generic method example> > static> > void> genericDisplay(T element)> > {> > System.out.println(element.getClass().getName()> > +> ' = '> + element);> > }> > // Driver method> > public> static> void> main(String[] args)> > {> > // Calling generic method with Integer argument> > genericDisplay(> 11> );> > // Calling generic method with String argument> > genericDisplay(> 'GeeksForGeeks'> );> > // Calling generic method with double argument> > genericDisplay(> 1.0> );> > }> }> |
>
>Ausgabe
java.lang.Integer = 11 java.lang.String = GeeksForGeeks java.lang.Double = 1.0>
Generics funktionieren nur mit Referenztypen:
Wenn wir eine Instanz eines generischen Typs deklarieren, muss das an den Typparameter übergebene Typargument ein Referenztyp sein. Wir können keine primitiven Datentypen wie verwenden int , verkohlen.
Test obj = new Test(20);>
Die obige Zeile führt zu einem Fehler bei der Kompilierung, der mithilfe von Typ-Wrappern zur Kapselung eines primitiven Typs behoben werden kann.
Aber Arrays primitiver Typen können an den Typparameter übergeben werden, da Arrays Referenztypen sind.
ArrayList a = new ArrayList();>
Generische Typen unterscheiden sich anhand ihrer Typargumente:
Betrachten Sie den folgenden Java-Code.
Java
// Java program to show working> // of user-defined Generic classes> // We use to specify Parameter type> class> Test {> > // An object of type T is declared> > T obj;> > Test(T obj) {> this> .obj = obj; }> // constructor> > public> T getObject() {> return> this> .obj; }> }> // Driver class to test above> class> Main {> > public> static> void> main(String[] args)> > {> > // instance of Integer type> > Test iObj => new> Test(> 15> );> > System.out.println(iObj.getObject());> > // instance of String type> > Test sObj> > => new> Test(> 'GeeksForGeeks'> );> > System.out.println(sObj.getObject());> > iObj = sObj;> // This results an error> > }> }> |
>
>
Ausgabe:
error: incompatible types: Test cannot be converted to Test>
Obwohl iObj und sObj vom Typ Test sind, verweisen sie auf unterschiedliche Typen, da sich ihre Typparameter unterscheiden. Generics erhöhen dadurch die Typsicherheit und verhindern Fehler.
Typparameter in Java Generics
Die Namenskonventionen für Typparameter sind wichtig, um Generika gründlich zu erlernen. Die allgemeinen Typparameter lauten wie folgt:
vlc zum Herunterladen von YouTube
- T – Typ
- E – Element
- K – Schlüssel
- N – Nummer
- V – Wert
Vorteile von Generika:
Programme, die Generics verwenden, haben viele Vorteile gegenüber nicht generischem Code.
1. Code-Wiederverwendung: Wir können eine Methode/Klasse/Schnittstelle einmal schreiben und sie für jeden gewünschten Typ verwenden.
2. Typensicherheit: Generika führen dazu, dass Fehler beim Kompilieren und nicht zur Laufzeit auftreten (Es ist immer besser, Probleme in Ihrem Code zur Kompilierungszeit zu kennen, als dass Ihr Code zur Laufzeit fehlschlägt). Angenommen, Sie möchten eine ArrayList erstellen, die die Namen der Schüler speichert, und wenn der Programmierer versehentlich ein ganzzahliges Objekt anstelle einer Zeichenfolge hinzufügt, lässt der Compiler dies zu. Wenn wir diese Daten jedoch von ArrayList abrufen, führt dies zur Laufzeit zu Problemen.
Java
// Java program to demonstrate that NOT using> // generics can cause run time exceptions> import> java.util.*;> class> Test> {> > public> static> void> main(String[] args)> > {> > // Creatinga an ArrayList without any type specified> > ArrayList al => new> ArrayList();> > al.add(> 'Sachin'> );> > al.add(> 'Rahul'> );> > al.add(> 10> );> // Compiler allows this> > String s1 = (String)al.get(> 0> );> > String s2 = (String)al.get(> 1> );> > // Causes Runtime Exception> > String s3 = (String)al.get(> 2> );> > }> }> |
>
>
Ausgabe :
Exception in thread 'main' java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at Test.main(Test.java:19)>
Wie lösen Generika dieses Problem?
Bei der Definition von ArrayList können wir angeben, dass diese Liste nur String-Objekte aufnehmen kann.
Java
// Using Java Generics converts run time exceptions into> // compile time exception.> import> java.util.*;> class> Test> {> > public> static> void> main(String[] args)> > {> > // Creating a an ArrayList with String specified> > ArrayList al => new> ArrayList ();> > al.add(> 'Sachin'> );> > al.add(> 'Rahul'> );> > // Now Compiler doesn't allow this> > al.add(> 10> );> > String s1 = (String)al.get(> 0> );> > String s2 = (String)al.get(> 1> );> > String s3 = (String)al.get(> 2> );> > }> }> |
Nick Pulos schwarzer Blitz
>
>
Ausgabe:
15: error: no suitable method found for add(int) al.add(10); ^>
3. Eine individuelle Typumsetzung ist nicht erforderlich: Wenn wir keine Generika verwenden, müssen wir im obigen Beispiel jedes Mal, wenn wir Daten aus ArrayList abrufen, diese typisieren. Die Typumwandlung bei jedem Abrufvorgang bereitet große Kopfschmerzen. Wenn wir bereits wissen, dass unsere Liste nur Zeichenfolgendaten enthält, müssen wir sie nicht jedes Mal typisieren.
Java
// We don't need to typecast individual members of ArrayList> import> java.util.*;> class> Test {> > public> static> void> main(String[] args)> > {> > // Creating a an ArrayList with String specified> > ArrayList al => new> ArrayList();> > al.add(> 'Sachin'> );> > al.add(> 'Rahul'> );> > // Typecasting is not needed> > String s1 = al.get(> 0> );> > String s2 = al.get(> 1> );> > }> }> |
>
>
4. Generics fördert die Wiederverwendbarkeit von Code: Mithilfe von Generika in Java können wir Code schreiben, der mit verschiedenen Datentypen funktioniert. Zum Beispiel,
Nehmen wir an, wir möchten die Array-Elemente verschiedener Datentypen wie int, char, String usw. sortieren.
Grundsätzlich benötigen wir unterschiedliche Funktionen für unterschiedliche Datentypen.
Der Einfachheit halber verwenden wir die Blasensortierung.
Aber durch die Verwendung Generika, Wir können die Funktion zur Wiederverwendbarkeit von Code erreichen.
Java
public> class> GFG {> > public> static> void> main(String[] args)> > {> > Integer[] a = {> 100> ,> 22> ,> 58> ,> 41> ,> 6> ,> 50> };> > Character[] c = {> 'v'> ,> 'g'> ,> 'a'> ,> 'c'> ,> 'x'> ,> 'd'> ,> 't'> };> > String[] s = {> 'Virat'> ,> 'Rohit'> ,> 'Abhinay'> ,> 'Chandu'> ,> 'Sam'> ,> 'Bharat'> ,> 'Kalam'> };> > System.out.print(> 'Sorted Integer array : '> );> > sort_generics(a);> > System.out.print(> 'Sorted Character array : '> );> > sort_generics(c);> > System.out.print(> 'Sorted String array : '> );> > sort_generics(s);> > > }> > public> static> extends Comparable>void sort_generics(T[] a) { //Da wir die nicht-primitiven Datentypen vergleichen //wir müssen die Klasse Comparable verwenden //Bubble Sort-Logik for (int i = 0; i 1; i++) { for (int j = 0; j 1; j++) { if (a[j].compareTo(a[j + 1])> 0) { swap(j, j + 1, a); } } } // Die Elemente nach der Sortierung drucken for (T i : a) { System.out.print(i + ', '); } System.out.println(); } public static void swap(int i, int j, T[] a) { T t = a[i]; a[i] = a[j]; a[j] = t; } }> |
>
Madhuri sagte, komm schon
>Ausgabe
Sorted Integer array : 6, 22, 41, 50, 58, 100, Sorted Character array : a, c, d, g, t, v, x, Sorted String array : Abhinay, Bharat, Chandu, Kalam, Rohit, Sam, Virat,>
Hier haben wir eine generische Methode erstellt. Dieselbe Methode kann verwendet werden, um Operationen an ganzzahligen Daten, Zeichenfolgendaten usw. durchzuführen.
5. Implementierung generischer Algorithmen: Durch die Verwendung von Generika können wir Algorithmen implementieren, die auf verschiedenen Objekttypen funktionieren und gleichzeitig typsicher sind.