Les génériques Java (Generics) sont une nouvelle fonctionnalité introduite dans JDK5 qui permet l'utilisation de paramètres de type (Type Parameter) lors de la définition de classes et d'interfaces. Les paramètres de type déclarés sont remplacés par des types spécifiques lorsqu'ils sont utilisés. L'application la plus importante des génériques se trouve désormais dans le nouveau cadre de classes de collection du JDK5, où Map et List sont utilisés. Les avantages sont évidents. Nous pouvons étendre davantage de classes horizontalement. Les inconvénients sont en fait ses avantages, car lorsque nous utilisons des classes génériques, nous devons être très clairs sur le but de notre code et ne pouvons pas utiliser de type.
La classe générique la plus basique
Copiez le code comme suit :
paquet com.garinzhang.javabase.generic.e1 ;
/**
* La classe générique la plus basique, le type est défini par vous-même
* @auteur Garin Zhang
*
* @param <T>
*/
classe publique Point<T> {
var T privé ;
public T getVar() {
retourner var;
}
public void setVar (T var) {
this.var = var;
}
}
paquet com.garinzhang.javabase.generic.e1 ;
classe publique GenericExample {
/**
* @param arguments
*/
public static void main (String[] arguments) {
Point<String> p = nouveau Point<String> ();
p.setVar("codeur");
System.out.println(p.getVar());
}
}
Plusieurs types génériques
Copiez le code comme suit :
paquet com.garinzhang.javabase.generic.e2 ;
/**
* Plusieurs types génériques. Généralement, il est préférable d'utiliser des lettres proches de T, telles que S, R, etc.
* @auteur Garin Zhang
*
* @param <T>
* @param <S>
*/
classe publique Bloc-notes<T, S> {
clé T privée ;
valeur S privée ;
public T getKey() {
renvoie this.key ;
}
public S getValue() {
renvoie this.value ;
}
public void setKey (clé T) {
this.key = clé ;
}
public void setValue (valeur S) {
this.value = valeur ;
}
}
paquet com.garinzhang.javabase.generic.e2 ;
classe publique GenericExample {
/**
* @param arguments
*/
public static void main (String[] arguments) {
Bloc-notes<String, Integer> p = nouveau Bloc-notes<String, Integer> ();
p.setKey("codeur");
p.setValue(99999);
System.out.println("key: " + p.getKey());
System.out.println("value: " + p.getValue());
}
}
Utilisez le caractère générique "?" dans les paramètres de la méthode
Copiez le code comme suit :
paquet com.garinzhang.javabase.generic.e3 ;
/**
* La clé de cet exemple se trouve dans la méthode main
* @auteur Garin Zhang
*
* @param <T>
*/
classe publique Info<T> {
clé T privée ;
public T getKey() {
renvoie this.key ;
}
public void setKey (clé T) {
this.key = clé ;
}
@Outrepasser
chaîne publique toString() {
renvoie this.key.toString();
}
}
paquet com.garinzhang.javabase.generic.e3 ;
/**
* Utiliser des caractères génériques dans les paramètres de méthode
* @auteur Garin Zhang
*
*/
classe publique GenericExample {
/**
* @param arguments
*/
public static void main (String[] arguments) {
Info<String> i = new Info<String>();
i.setKey("codeur");
amusant(je);
Info<Integer> j = new Info<Integer>();
j.setKey(9999);
amusant(j);
}
public static void fun(Info<?> temp) {
System.out.println("Contenu : " + temp);
}
}
La transformation vers le haut échoue
Copiez le code comme suit :
paquet com.garinzhang.javabase.generic.e4 ;
/**
* La clé de cet exemple se trouve dans la méthode main
* @auteur Garin Zhang
*
* @param <T>
*/
classe publique Info<T> {
clé T privée ;
public T getKey() {
renvoie this.key ;
}
public void setKey (clé T) {
this.key = clé ;
}
@Outrepasser
chaîne publique toString() {
renvoie this.key.toString();
}
}
paquet com.garinzhang.javabase.generic.e4 ;
classe publique GenericExample {
/**
* @param arguments
*/
public static void main (String[] arguments) {
Info<String> strEg = new Info<String>();
Info<Object> objEg;
// Erreur de compilation « Incompatibilité de type : impossible de convertir d'Info<String> en Info<Object> »
// Échec de la mise à niveau, chaîne -> objet
// objEg = strEg;
}
}
L'utilisation de génériques dans les interfaces
Copiez le code comme suit :
paquet com.garinzhang.javabase.generic.e5 ;
/**
* La clé de cet exemple se trouve dans la méthode main
* @auteur Garin Zhang
*
* @param <T>
*/
Informations sur l'interface<T> {
public TgetVar();
}
paquet com.garinzhang.javabase.generic.e5 ;
/**
* Classe générique
* @auteur Garin Zhang
*
* @param <T>
*/
la classe publique InfoImpl<T> implémente Info<T> {
var T privé ;
public InfoImpl(T var) {
this.setVar(var);
}
public void setVar (T var) {
this.var = var;
}
public T getVar() {
renvoie this.var;
}
}
paquet com.garinzhang.javabase.generic.e5 ;
/**
*Classe non générique
* @auteur Garin Zhang
*
* @param <T>
*/
la classe publique InfoImpl1 implémente Info<String> {
variable de chaîne privée ;
public InfoImpl1 (var de chaîne) {
this.setVar(var);
}
public void setVar(String var) {
this.var = var;
}
chaîne publique getVar() {
renvoie this.var;
}
}
paquet com.garinzhang.javabase.generic.e5 ;
classe publique GenericExample {
/**
* @param arguments
*/
public static void main (String[] arguments) {
Info<String> strEg = new InfoImpl<String>("coder");
System.out.println("Contenu : " + strEg.getVar());
Info<String> strEg1 = new InfoImpl1("coder1");
System.out.println("Contenu : " + strEg1.getVar());
}
}
Caractères génériques et utilisation d'extensions et de super
Copiez le code comme suit :
paquet com.garinzhang.javabase.generic.e6 ;
/**
* La clé de cet exemple se trouve dans la méthode main
* @auteur Garin Zhang
*
* @param <T>
*/
classe publique Info<T> {
clé T privée ;
public T getKey() {
renvoie this.key ;
}
public void setKey (clé T) {
this.key = clé ;
}
@Outrepasser
chaîne publique toString() {
renvoie this.key.toString();
}
}
paquet com.garinzhang.javabase.generic.e6 ;
classe publique GenericExample {
/**
* @param arguments
*/
public static void main (String[] arguments) {
Info<String> strEg = new Info<String>();
strEg.setKey("codeur");
//Erreur de compilation "La méthode fun(Info<? extends Number>) dans le type GenericExample n'est pas applicable pour les arguments (Info<String>)"
// upTypeLimit(i);
// Utilisez les types Entier ou Nombre.
Info<Integer> intEg = new Info<Integer>();
intEg.setKey(9999);
upTypeLimit(intEg);
//Erreur de compilation "La méthode downTypeLimit(Info<? super String>) dans le type GenericExample n'est pas applicable pour les arguments (Info<Integer>)"
// downTypeLimit(intEg);
// Puisque super est utilisé, downTypeLimit ne peut recevoir que String lui-même et Object
// Vérification de la relation d'héritage de String, aucune autre classe n'est héritée, uniquement Object
downTypeLimit(strEg);
Info<Object> objEg = new Info<Object>();
objEg.setKey(999);
downTypeLimit(objEg);
}
/**
* <? extends T> représente la limite supérieure du type, indiquant que le type paramétré peut être T ou une sous-classe de T
* @param temp
*/
public static void upTypeLimit(Info<? extends Number> temp) {
System.out.println("Contenu : " + temp);
}
/**
* <? super T> représente la limite inférieure du type (appelée qualification de super type dans Java Core), indiquant que le type paramétré est le super type (type parent) de ce type, jusqu'à ce que Object
* Dans cet exemple, cela signifie que T ne peut être qu'un objet ou une chaîne, car String n'hérite que d'un objet.
* @param temp
*/
public static void downTypeLimit(Info<? super String> temp) {
System.out.println("Contenu : " + temp);
}
}
Génériques de méthode, plusieurs génériques dans la méthode
Copiez le code comme suit :
paquet com.garinzhang.javabase.generic.e7 ;
/**
* Génériques de méthode, plusieurs génériques dans la méthode
* @auteur Garin Zhang
*
* @param <T>
*/
Informations sur la classe publique {
/**
* Format : modification de méthode <liste de types séparés par des virgules> nom de la méthode de type de valeur de retour (liste de paramètres)
* Par exemple : public <T, S> T fun(T t, S s)
* @paramt
* @params
* @retour
*/
public <T, S> T fun(T t, S s) {
System.out.println(s.toString());
retourner t ;
}
}
paquet com.garinzhang.javabase.generic.e7 ;
classe publique GenericExample {
/**
* @param arguments
*/
public static void main (String[] arguments) {
Info info = new Info();
String str = info.fun("coder", "imprimer le deuxième paramètre générique");
System.out.println(str);
int i = info.fun(30, "imprimer à nouveau le deuxième paramètre");
System.out.println(i);
}
}
Le type générique transmis ou renvoyé dans la méthode est déterminé par le type de paramètre défini lors de l'appel de la méthode.
Copiez le code comme suit :
paquet com.garinzhang.javabase.generic.e8 ;
/**
* s'étend
* @auteur Garin Zhang
*
* @param <T>
*/
classe publique Info<T étend le numéro> {
var T privé ;
public T getVar() {
renvoie this.var;
}
public void setVar (T var) {
this.var = var;
}
@Outrepasser
chaîne publique toString() {
renvoie this.var.toString();
}
}
paquet com.garinzhang.javabase.generic.e8 ;
classe publique GenericExample {
/**
* @param arguments
*/
public static void main (String[] arguments) {
Info<Integer> intEg = fun(30); // Le type ici a été déterminé comme étant Integer
System.out.println(intEg.getVar());
}
/**
* Le type générique transmis ou renvoyé dans la méthode est déterminé par le type de paramètre défini lors de l'appel de la méthode.
* @param param
* @retour
*/
public static <T étend le numéro> Info<T> fun(T param) {
Info<T> temp = new Info<T>();
temp.setVar(param);
température de retour ;
}
}
Rendre cohérents les deux types de paramètres passés dans la méthode
Copiez le code comme suit :
paquet com.garinzhang.javabase.generic.e9 ;
/**
* Voir principal
* @auteur Garin Zhang
*
* @param <T>
*/
classe publique Info<T> {
var T privé ;
public T getVar() {
renvoie this.var;
}
public void setVar (T var) {
this.var = var;
}
@Outrepasser
chaîne publique versChaîne() {
renvoie this.var.toString();
}
}
paquet com.garinzhang.javabase.generic.e9 ;
classe publique GenericExample {
/**
* @param arguments
*/
public static void main (String[] arguments) {
Info<String> i1 = new Info<String>();
i1.setVar("Bonjour");
Info<String> i2 = new Info<String>();
i2.setVar("Codeur");
Info<Integer> i3 = new Info<Integer>();
i3.setVar(999);
ajouter(i1, i2);
//Erreur de compilation "La méthode add(Info<T>, Info<T>) dans le type GenericExample n'est pas applicable pour les arguments (Info<String>, Info<Integer>)"
// ajouter(i1, i3);
}
/**
* Les deux types de paramètres passés dans la méthode doivent être cohérents
* @paramparam
* @retour
*/
public static <T> void add(Info<T> i1, Info<T> i2) {
System.out.println(i1.getVar() + ":" + i2.getVar());
}
}
Génériques, paramètres variables, similaires à l'objet Arguments en JavaScript
Copiez le code comme suit :
paquet com.garinzhang.javabase.generic.e10 ;
classe publique GenericExample {
/**
* @param arguments
*/
public static void main (String[] arguments) {
Entier i[] = fun(1, 2, 3, 4, 5, 6);
amusant2(je);
}
public static <T> T[] fun(T... arg) {
retourner l'argument ;
}
public static <T> void fun2(T param[]) {
System.out.println("tableau générique : ");
pour(T t : param) {
System.out.println(t + " ,");
}
}
}
Imbrication générique : utilisez des classes génériques comme paramètres ; déterminez la valeur de retour en fonction du type de valeur de retour.
Copiez le code comme suit :
paquet com.garinzhang.javabase.generic.e11 ;
/**
* Accepte deux types génériques
* @auteur Garin Zhang
*
* @param <T>
*/
classe publique Info<T, V> {
var T privé ;
valeur V privée ;
public T getVar() {
renvoie this.var;
}
public void setVar (T var) {
this.var = var;
}
public V getValue(){
renvoie this.value ;
}
public void setValue (valeur V) {
this.value = valeur ;
}
@Outrepasser
chaîne publique versChaîne() {
renvoie this.var.toString();
}
}
paquet com.garinzhang.javabase.generic.e11 ;
/**
* Accepte 1 type générique
* @auteur Garin Zhang
*
* @param <T>
*/
Démo de classe publique<S> {
informations S privées ;
Démo(S) publique(s) {
this.setInfo(info);
}
public void setInfo(S infos) {
this.info = infos ;
}
public S getInfo() {
renvoyer this.info ;
}
}
paquet com.garinzhang.javabase.generic.e11 ;
importer java.util.List ;
importer com.google.common.collect.Lists ;
classe publique GenericExample {
/**
* @param arguments
*/
public static void main (String[] arguments) {
Démo<Info<String, Integer>> d;
Info<String, Integer> i ;
i = new Info<String, Integer>();
i.setVar("Codeur");
je.setValue(999);
d = new Demo<Info<String,Integer>>(i);
System.out.println("Contenu : " + d.getInfo().getVar());
System.out.println("Content: " + d.getInfo().getValue());
System.out.println(query(1, 2, 3, 4, 5).toString()); // [1, 2, 3, 4, 5]
// Avertissement "Sécurité du type : Un tableau générique de Object&Comparable<?>&Seriallessly est créé pour un paramètre varargs"
System.out.println(query(1, 2, 3, "StringType").toString()); // [1, 2, 3, StringType]
System.out.println(query("I ", "am", "a ", "coder").toString());// [Je , suis , a , codeur]
List<String> list = Lists.newArrayList("I ", "am", "a", "coder");
System.out.println(list.toString()); // [Je, suis, un, codeur]
}
/**
* Déterminez le type générique via la valeur de retour. Le type de valeur de retour dans cette méthode est automatiquement généré par la définition de la méthode.
* Éléments @param
* @retour
*/
public static <E> List<E> requête (E... éléments) {
// https://github.com/exitsoft/exit-web-framework/commit/1d2f1098a2a4b6abab175b793e2308aa8bd0ea16.
//importer com.google.common.collect.Lists ;
// <dépendance>
// <groupId>com.google.guava</groupId>
// <artifactId>goyave</artifactId>
// <version>16.0.1</version>
// </dépendance>
return Lists.newArrayList(elements);
}
}