Si je devais vous dire directement ce que sont les génériques, je ne peux vraiment pas. Voici une question :
Définissez une classe de points de coordonnées pouvant enregistrer différents types de données, tels que des entiers, des types à virgule flottante et des types de chaînes.
Étant donné que le type de variable est incertain au début, il est facile de penser à utiliser la classe parent de tous les types, c'est-à-dire la classe Object.
Fini les bêtises, utilisez le code pour le refléter
Exemple 1 : utiliser un objet pour implémenter une entrée de type de données incertain
//Utiliser un objet pour représenter des types incertains
Point public (Objet x, Objet y) {
this.setX(x);
this.setY(y);
}
public void setX (Objet x) {
ceci.x = x;
}
Objet public getX() {
renvoyer x ;
}
public void setY (Objet y) {
ceci.y = y;
}
Objet public getY() {
retourner y ;
}
}
//classe de test
Démo de classe publique {
public static void main (String[] arguments) {
System.out.println("Utiliser des nombres à virgule flottante pour représenter les coordonnées : ");
Point p = nouveau Point(12.23,23.21) ;
//Ici, la classe Object est convertie en classe Double, puis automatiquement déballée. Les deux suivantes sont identiques.
System.out.println("Coordonnées X" + (Double)p.getX());
System.out.println("Coordonnées Y" + (Double)p.getY());
System.out.println();
System.out.println("Utiliser des entiers pour représenter les coordonnées : ");
Point p2 = nouveau Point(12, 23) ;
System.out.println("Coordonnées de X" + (Integer)p2.getX());
System.out.println("Coordonnées Y" + (Integer)p2.getY());
System.out.println();
System.out.println("Représentation des coordonnées sous forme de chaîne : ");
Point p3 = nouveau Point("29 degrés de latitude nord", "113 degrés de longitude est");
System.out.println("Coordonnées X" + (String)p3.getX());
System.out.println("Coordonnées Y" + (String)p3.getY());
}
}
Vous devez clairement comprendre quel type vous transmettez, puis le baisser avant de pouvoir l'utiliser.
Bien que cela réponde à la demande, cela implique également un facteur de danger. Pourquoi dit-on que c'est implicite ?
Par exemple, nous utilisons new Point(12.23, "29 degrés de latitude nord") pour construire un objet Point
Utilisez ensuite (Double) pour le transformer vers le bas. Quel sera le résultat ?
Oui, la compilation réussira, mais une fois exécutée, une exception de conversion de type se produira
Il est également très simple d'éviter les exceptions de conversion de classe. Il suffit de remplacer la déclaration Object par une déclaration de type fixe (telle que : String x, String y), afin qu'une erreur soit signalée lors de la compilation.
Ensuite, vous pourrez trouver les erreurs et apporter des corrections
Mais nous ne pourrons alors pas répondre à la demande.
Afin d'éviter les risques de sécurité et de remplacer différents types de données, ces personnes talentueuses ont introduit le concept de génériques dans JDK1.5.
Voyons comment réécrire le code ci-dessus en utilisant des génériques
Exemple 2 : classe générique
Démo de classe publique {
public static void main (String[] arguments) {
System.out.println("Utiliser des nombres à virgule flottante pour représenter les coordonnées : ");
//Après réécriture avec des génériques, il n'est pas nécessaire d'effectuer une transformation descendante sur les données utilisées.
Point<Double> p = nouveau Point<Double>(12.23,23.21);
System.out.println("Coordonnées X" + p.getX());
System.out.println("Coordonnées Y" + p.getY());
System.out.println();
System.out.println("Utiliser des entiers pour représenter les coordonnées : ");
Point<Integer> p2 = nouveau Point<Integer>(12, 23);
System.out.println("Coordonnées X" + p2.getX());
System.out.println("Coordonnées Y" + p2.getY());
System.out.println();
System.out.println("Représentation des coordonnées sous forme de chaîne : ");
Point<String> p3 = new Point<String>("29 degrés de latitude nord", "113 degrés de longitude est");
System.out.println("Coordonnée X" + p3.getX());
System.out.println("Coordonnées Y" + p3.getY());
}
}
Si nous transmettons délibérément différents types de données à ce moment :
Point<Double> p = new Point<Double>("29 degrés de latitude nord",12.22);
Ensuite, une erreur sera signalée lors de la compilation
Bien que les génériques soient définis, si vous n'utilisez pas le mécanisme générique dans le constructeur, il traitera les données comme des objets.
Le but de ceci est principalement d'être compatible avec les anciens codes antérieurs à JDK1.4, comme
Point p = nouveau Point(22.11,23.21) ;
Le résultat final de l'exécution est le même, mais un message d'avertissement sera affiché lors de la compilation.
Exemple 3 : méthodes génériques
Comme vous pouvez le voir dans l'exemple ci-dessus, une fois le type d'objet spécifié dans le constructeur, le même type sera utilisé dans toute la classe.
L'exemple le plus typique est utilisé dans le framework de collection, tel que : ArrayList<Integer> al = new ArrayList<Integer>();
À l’heure actuelle, tous les types d’objets exploités dans al sont des entiers.
Cependant, parfois, nous ne souhaitons pas fixer l'objet de l'opération, mais souhaitons utiliser la technologie générique de manière plus flexible.
A ce moment, vous pouvez essayer la méthode générique
public <E> void show(E e) {
System.out.println(e);
}
}
Démo de classe publique {
public static void main (String[] arguments) {
Imprimer p = new Imprimer();
p.print(12);
p.print("bonjour");
p.show(nouveau Integer(33));
p.show(23);
}
}
En fait, de cette manière, il n'y a pas de grande différence avec l'utilisation d'objets Object dans les méthodes.
De plus, après JDK1.5, la fonction de déballage automatique a été ajoutée, éliminant ainsi le besoin de transformation vers le bas.
Exemple 4 : Interface générique
//Méthode d'implémentation 1 :
la classe InterDemo1 implémente Inter<String> {
impression publique nulle (Chaîne t) {
System.out.println("print: " + t);
}
}
//Méthode d'implémentation deux :
la classe InterDemo2<T> implémente Inter<T> {
impression publique nulle (T t) {
System.out.println("print: " + t);
}
}
Démo de classe {
public static void main (String[] arguments) {
InterDemo1 id1 = new InterDemo1();
id1.print("bonjour");
InterDemo2<Integer> id2 = new InterDemo2<Integer>();
id2.print(nouveau Integer(23));
}
}
Il existe deux manières d'implémenter une interface générique. La première consiste à spécifier le type générique lors de son implémentation.
L'autre consiste à continuer d'utiliser des génériques et de déterminer le type générique lors de la construction.