java generics tutorial with examples
Les génériques Java sont un ensemble de fonctionnalités qui vous permettent d'écrire du code indépendamment du type de données. Cet article explique en détail les génériques Java avec des exemples:
Les génériques sont l'une des fonctionnalités importantes de Java et ont été introduits à partir de Java 5.
Par définition, les génériques sont un ensemble de fonctionnalités du langage Java qui permettent au programmeur d'utiliser des types et des fonctions génériques et ainsi assurer la sécurité des types.
Ce que vous apprendrez:
Comment fonctionnent les génériques en Java?
Si vous avez déjà travaillé avec C ++, Java Generics est identique aux modèles en C ++. Les génériques Java vous permettent d'inclure un paramètre dans votre définition de classe / méthode qui aura la valeur d'un type de données primitif.
Par exemple, vous pouvez avoir une classe générique «Array» comme suit:
Tableau de classes {….}
Où est le type paramétré.
Ensuite, vous pouvez créer des objets pour cette classe comme suit:
Array int_array = new Array () Array char_array = new Array ();
Donc, étant donné une classe paramétrée générique, vous pouvez créer des objets de la même classe avec différents types de données comme paramètres. C'est l'essence principale de l'utilisation de Java Generics.
De même, vous pouvez écrire une méthode générique avec un type paramétré pour trier un tableau, puis instancier cette méthode sur n'importe quel type primitif.
Les génériques Java sont principalement utilisés avec le framework de collections de Java. Les différentes collections comme LinkedList, List, Map, HashMap, etc. utilisent des génériques pour l'implémentation. Les génériques fournissent une sécurité de type car la vérification de type est effectuée au moment de la compilation, ce qui rend votre code plus stable.
Voyons maintenant plus en détail les classes et méthodes génériques ainsi que d'autres sujets connexes.
Classes génériques
Une classe générique est identique à une classe normale, sauf que le nom de la classe est suivi d'un type entre crochets angulaires.
Une définition générale d'une classe générique est la suivante:
classe nom_classe
{
variables de classe;
… ..
méthodes de classe;
}
Une fois la classe définie, vous pouvez créer des objets de n'importe quel type de données de votre choix comme suit:
class_name obj = new class_name ();
Par exemple, pour l'objet Integer, la déclaration sera:
class_name obj = new class_name;
De même, pour le type de données String, l'objet sera:
class_name str_Obj = new class_name;
Un exemple d'implémentation pour la classe Generic est illustré ci-dessous.
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()); } }
Production:
Dans le programme ci-dessus, une classe MyGenericClass est une classe générique. Il a deux méthodes, à savoir ajouter et obtenir. La méthode add initialise l'objet générique tandis que les méthodes get renvoient l'objet.
Dans la fonction principale, nous déclarons deux objets de type Integer et String chacun. Nous initialisons ces deux objets avec leurs valeurs initiales respectives à l'aide de la méthode add, puis sortons le contenu de ces objets à l'aide de la méthode get.
Nous avons présenté l'exemple de classe générique ci-dessus avec un paramètre de type. Mais en réalité, une classe peut également avoir plus d'un paramètre de type. Dans ce cas, les paramètres de type sont séparés par une virgule.
L'exemple suivant illustre ceci:
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(); } }
Production:
Dans ce programme, nous avons deux paramètres de type, à savoir T1 et T2. Nous avons des fonctions pour initialiser les objets membres et aussi pour imprimer le contenu. Dans la fonction principale, nous déclarons un objet avec deux types, à savoir String et Integer. La sortie du programme affiche le contenu de l'objet créé.
Tout comme les classes, vous pouvez également avoir des interfaces génériques. Nous apprendrons tout sur les interfaces dans une rubrique distincte.
Méthodes génériques Java
Tout comme vous pouvez avoir des classes et des interfaces génériques, vous pouvez également avoir des méthodes génériques au cas où vous n'auriez pas besoin d'une classe entière pour être générique.
Le programme suivant montre l'implémentation de la méthode générique «printGenericArray». Notez l'appel de méthode dans la fonction principale. Ici, nous faisons deux appels à la méthode Generic, d'abord avec type puis avec 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 ); } }
Production:
Paramètres de type borné
Les paramètres de type borné apparaissent lorsque vous souhaitez limiter les types de données dans les génériques. Par exemple, si vous voulez qu'une classe ou une méthode générique particulière ou une interface ne fonctionne que pour les types de données numériques, vous pouvez le spécifier en utilisant le mot-clé «extend».
Ceci est montré ci-dessous:
List myList = new ArrayList(); List list1 = new ArrayList();
Les deux déclarations ci-dessus seront acceptées par le compilateur car Long et Integer sont des sous-classes de Number.
La prochaine déclaration, cependant, sera un problème.
List list = new ArrayList();
Cela donnera une erreur de compilation car String n'est pas un nombre. Le symbole «?» Dans l'exemple ci-dessus est appelé joker et nous en discuterons ensuite.
Ainsi, en général, les paramètres de type borné sont principalement utilisés lorsque vous souhaitez restreindre les types de données à utiliser dans votre code générique.
Caractère générique Java Generics
En Java, un caractère générique est indiqué par un point d’interrogation, «?», Utilisé pour désigner un type inconnu. Les caractères génériques sont principalement utilisés avec les génériques comme type de paramètre.
Lorsque vous utilisez des caractères génériques génériques, vous devez vous souvenir d'un point: bien que l'objet soit la superclasse de toutes les autres classes, la collection d'objets ( Par exemple, List) n'est pas une superclasse de toutes les autres collections.
En plus d'être utilisé comme type de paramètre, vous pouvez utiliser un caractère générique comme champ, variable locale et en tant que tel. Cependant, vous ne pouvez jamais utiliser un caractère générique comme supertype, ou comme argument de type pour invoquer une méthode générique ou en cas de création d'une instance d'une classe générique.
Il existe de nombreux exemples de types paramétrés par joker (ici au moins un argument de type est un joker) comme indiqué ci-dessous et les jokers utilisés à différents endroits seront interprétés différemment:
- Collection <: Collection désigne toute instanciation d'interface de collection, quel que soit l'argument de type utilisé.
- Lister extends Number< : Liste représente tous les types de liste où le type d'élément sera un nombre.
- Comparateur: Toutes les instanciations d'interface de comparateur pour les arguments de type qui sont des Stringsupertypes.
Notez qu'un type paramétré Wildcard est une règle imposée pour reconnaître les types valides. Ce n'est pas un type de données concret. Les jokers génériques peuvent être limités ou illimités.
# 1) Wildcards illimités
Dans les caractères génériques sans limites, il n'y a aucune restriction sur les variables de type et est désigné comme suit:
ArrayList mylist = new ArrayList(); ArrayList my_strList = new ArrayList();
# 2) Cartes génériques délimitées
Nous avons déjà discuté des types bornés. Ceux-ci mettent les restrictions sur le type de données utilisé pour instancier les paramètres de type à l'aide des mots-clés - extend ou super. Ces jokers peuvent être divisés en jokers Upper Bounded et Lower Bounded Wildcards.
- Caractères génériques à limite supérieure
Si vous souhaitez que votre expression générique soit valide pour toutes les sous-classes d'un type donné, vous spécifiez le caractère générique de limite supérieure avec le mot clé extend.
Par exemple, supposons que vous ayez besoin d'une méthode générique qui prend en charge List, List, etc., alors vous pouvez spécifier un caractère générique à limite supérieure comme Lister . Comme Number est une superclasse, cette méthode générique fonctionnera pour toutes ses sous-classes.
Le programme suivant le démontre.
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)); } }
Production:
Ici, nous avons fourni un caractère générique de limite supérieure, List, à l'argument de type de la fonction «summation». Dans la fonction principale, nous définissons deux listes à savoir int_list de type Integer et doubles_list de type Double. Comme Integer et Double sont les sous-classes de Number, la sommation des fonctions fonctionne parfaitement sur ces deux listes.
- Caractères génériques à limite inférieure
Si vous souhaitez que l'expression générique accepte toutes les superclasses d'un type particulier, vous pouvez spécifier un caractère générique à limite inférieure pour votre argument de type.
Un exemple de mise en œuvre pour cela est donné ci-dessous:
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); } }
Production:
Dans ce programme, le caractère générique inférieur spécifié est «Liste». Ensuite, dans la fonction principale, nous avons une liste de types et la liste. Comme nous avons utilisé le Wildcard Lower Bounded, la classe Number est une superclasse de Integer est un argument de type valide.
Avantages des génériques Java
# 1) Sécurité de type
Les génériques garantissent la sécurité du type. Cela signifie que la vérification de type est effectuée au moment de la compilation plutôt qu'au moment de l'exécution. Il n'y a donc aucune chance d'obtenir «ClassCastException» pendant l'exécution car les types corrects seront utilisés.
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); } }
Dans le programme ci-dessus, nous avons deux listes, une sans génériques et une autre avec des génériques. Dans la liste non générique, il n'y a pas de sécurité de type. Vous pouvez ajouter un entier, une chaîne, etc. en tant qu'élément et il est accepté.
Dans la liste générique, vous ne pouvez ajouter qu'un seul type d'élément spécifié dans l'expression générique. Si vous essayez d'ajouter un élément d'un autre type, cela entraîne une erreur de compilation.
Dans le programme ci-dessus, l'erreur de compilation est clignotée à la ligne:
list.add('10');
# 2) Réutilisation du code
En utilisant les génériques, vous n'avez pas besoin d'écrire de code distinct pour chaque type de données. Vous pouvez écrire une seule classe ou méthode, etc. et l'utiliser pour tous les types de données.
# 3) Pas besoin de typage
comment convertir youtube en wav
Comme vous utilisez Generics, le compilateur connaît les types utilisés, il n'y a donc pas besoin de transtypage.
Considérez le code ci-dessous:
List mylist = new ArrayList(); mylist.add('Java'); String mystr = (String) list.get(0); //typecasting required
Comme vous pouvez le voir lorsqu'une liste normale est utilisée, vous devez transtyper l'élément de la liste dans son type approprié de la manière dont cela est fait pour le mystr ci-dessus.
Maintenant, écrivons à nouveau le même code avec une liste générique.
List list = new ArrayList(); list.add('Java'); String mystr = list.get(0);
Ici, nous avons spécifié le type de chaîne comme expression générique pour la déclaration de liste. Ainsi, pour récupérer des éléments individuels de cette liste, nous n'avons pas besoin de typer.
# 4) Implémenter des algorithmes génériques
Vous pouvez implémenter beaucoup plus d'algorithmes génériques lorsque vous utilisez des génériques pour coder.
# 5) Vérification à la compilation
Comme déjà mentionné, lorsque vous utilisez Generics dans votre programme Java, le compilateur vérifie les types au moment de la compilation, évitant ainsi l'arrêt anormal du programme lors de l'exécution.
Questions fréquemment posées
Q # 1) Pourquoi utilisons-nous des génériques en Java?
Répondre: Les génériques garantissent l'indépendance du type, c'est-à-dire que nous pouvons fournir un paramètre de type tout en définissant une classe / une interface / une méthode, etc. afin que lors de l'instanciation réelle, nous puissions spécifier le type réel. De cette façon, nous fournissons également la réutilisabilité du code.
Q # 2) Les génériques sont-ils importants en Java?
Répondre: Oui. En fait, les génériques sont les fonctionnalités les plus importantes de Java pour assurer la sécurité du type, c'est-à-dire la vérification du type au moment de la compilation.
Q # 3) Quand Java a-t-il ajouté des génériques?
Répondre: Les génériques ont été ajoutés à Java en 2004 avec J2SE 5.0 avec l'intention d'assurer la sécurité des types au moment de la compilation en Java.
Q # 4) Qu'est-ce qu'un type générique?
Répondre: Un type générique est une classe, une interface ou une méthode générique qui est fournie avec un paramètre de type. Cela permet la sécurité de type et la réutilisation du code.
Q # 5) Pouvons-nous utiliser Generics avec Array en Java?
Répondre: Non. Java n'autorise pas les tableaux génériques.
Conclusion
Ceci conclut le didacticiel sur les génériques Java, considéré comme l'une des fonctionnalités les plus importantes des versions récentes de Java. L'utilisation de génériques dans les programmes Java garantit la sécurité des types ainsi que la réutilisation du code. Il assure également la vérification à la compilation afin que le programme ne s'arrête pas à l'exécution.
Les génériques Java sont principalement utiles avec l'interface des collections Java dont nous parlerons en détail dans un autre tutoriel de cette série.
Bonne lecture!!
lecture recommandée
- 15 meilleurs outils JAVA pour le développement, la construction, le profilage, la couverture de code et la révision
- Tutoriel Java Collections Framework (JCF)
- Types de données Java, boucles, tableaux, commutateurs et assertions
- Déploiement Java: création et exécution d'un fichier JAR Java
- Exceptions Java et gestion des exceptions avec des exemples
- Tutoriel JAVA pour les débutants: plus de 100 tutoriels vidéo Java pratiques
- Tutoriel de réflexion Java avec des exemples
- Mot-clé Java 'this': Tutoriel avec des exemples de code