Tout ce que nous savons, c'est que « toutes les instances d'une classe quelconque partagent le même objet java.lang.Class de ce type de classe »
par exemple)
Student a = new Student();
Student b = new Student();
ensuite a.getClass() == b.getClass()
c'est vrai.
Supposons maintenant
Teacher t = new Teacher();
sans génériques, ce qui suit est possible.
Class studentClassRef = t.getClass();
Mais c'est faux maintenant ..?
par exemple) public void printStudentClassInfo(Class studentClassRef) {}
peut être appelé avecTeacher.class
Cela peut être évité en utilisant des génériques.
Class<Student> studentClassRef = t.getClass(); //Compilation error.
Maintenant, qu'est-ce que T ?? T est des paramètres de type (également appelés variables de type); délimité par des crochets (<>), suit le nom de la classe.
T est juste un symbole, comme un nom de variable (peut être n'importe quel nom) déclaré lors de l'écriture du fichier de classe. Plus tard, T sera remplacé par
un nom de classe valide lors de l'initialisation (HashMap<String> map = new HashMap<String>();
)
par exemple) class name<T1, T2, ..., Tn>
Class<T>
Représente donc un objet de classe de type de classe spécifique 'T
'.
Supposons que vos méthodes de classe doivent fonctionner avec des paramètres de type inconnus comme ci-dessous
/**
* Generic version of the Car class.
* @param <T> the type of the value
*/
public class Car<T> {
// T stands for "Type"
private T t;
public void set(T t) { this.t = t; }
public T get() { return t; }
}
Ici, T peut être utilisé comme String
type CarName
OU T peut être utilisé comme Integer
type comme modelNumber ,
OU T peut être utilisé comme Object
type d' instance de voiture valide .
Maintenant, voici le POJO simple qui peut être utilisé différemment au moment de l'exécution.
Collections, par exemple) List, Set, Hashmap sont les meilleurs exemples qui fonctionneront avec différents objets selon la déclaration de T, mais une fois que nous avons déclaré T comme chaîne,
par exemple)HashMap<String> map = new HashMap<String>();
Ensuite, il n'acceptera que les objets d'instance String Class.
Méthodes génériques
Les méthodes génériques sont des méthodes qui introduisent leurs propres paramètres de type. Cela revient à déclarer un type générique, mais la portée du paramètre type est limitée à la méthode où il est déclaré. Les méthodes génériques statiques et non statiques sont autorisées, ainsi que les constructeurs de classes génériques.
La syntaxe d'une méthode générique inclut un paramètre de type, entre crochets, et apparaît avant le type de retour de la méthode. Pour les méthodes génériques, la section des paramètres de type doit apparaître avant le type de retour de la méthode.
class Util {
// Generic static method
public static <K, V, Z, Y> boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
class Pair<K, V> {
private K key;
private V value;
}
Voici <K, V, Z, Y>
la déclaration des types utilisés dans les arguments de méthode qui devraient avant le type de retour qui estboolean
ici.
Dans le ci-dessous; la déclaration de type <T>
n'est pas requise au niveau de la méthode, car elle est déjà déclarée au niveau de la classe.
class MyClass<T> {
private T myMethod(T a){
return a;
}
}
Mais ci-dessous est faux car les paramètres de type au niveau de la classe K, V, Z et Y ne peuvent pas être utilisés dans un contexte statique (méthode statique ici).
class Util <K, V, Z, Y>{
// Generic static method
public static boolean compare(Pair<K, V> p1, Pair<Z, Y> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
D'AUTRES SCÉNARIOS VALIDES SONT
class MyClass<T> {
//Type declaration <T> already done at class level
private T myMethod(T a){
return a;
}
//<T> is overriding the T declared at Class level;
//So There is no ClassCastException though a is not the type of T declared at MyClass<T>.
private <T> T myMethod1(Object a){
return (T) a;
}
//Runtime ClassCastException will be thrown if a is not the type T (MyClass<T>).
private T myMethod1(Object a){
return (T) a;
}
// No ClassCastException
// MyClass<String> obj= new MyClass<String>();
// obj.myMethod2(Integer.valueOf("1"));
// Since type T is redefined at this method level.
private <T> T myMethod2(T a){
return a;
}
// No ClassCastException for the below
// MyClass<String> o= new MyClass<String>();
// o.myMethod3(Integer.valueOf("1").getClass())
// Since <T> is undefined within this method;
// And MyClass<T> don't have impact here
private <T> T myMethod3(Class a){
return (T) a;
}
// ClassCastException for o.myMethod3(Integer.valueOf("1").getClass())
// Should be o.myMethod3(String.valueOf("1").getClass())
private T myMethod3(Class a){
return (T) a;
}
// Class<T> a :: a is Class object of type T
//<T> is overriding of class level type declaration;
private <T> Class<T> myMethod4(Class<T> a){
return a;
}
}
Et enfin, la méthode statique a toujours besoin d'une <T>
déclaration explicite ; Il ne dérivera pas du niveau de la classe Class<T>
. Cela est dû au fait que le niveau de classe T est lié à l'instance.
Lisez aussi Restrictions sur les génériques
Caractères génériques et sous-typage
argument de type pour une méthode générique
De la documentation Java:
[...] Plus surprenant, la classe Class a été générée. Les littéraux de classe fonctionnent désormais comme des jetons de type, fournissant à la fois des informations de type à l'exécution et à la compilation. Cela permet un style d'usines statiques illustré par la méthode getAnnotation dans la nouvelle interface AnnotatedElement:
Il s'agit d'une méthode générique. Il déduit la valeur de son paramètre de type T de son argument et renvoie une instance appropriée de T, comme illustré par l'extrait de code suivant:
Avant les génériques, vous auriez dû convertir le résultat en auteur. De plus, vous n'auriez eu aucun moyen de faire vérifier au compilateur que le paramètre réel représentait une sous-classe d'Annotation. [...]
Eh bien, je n'ai jamais eu à utiliser ce genre de choses. N'importe qui?
la source
Class<? extends X>
notation, j'ai pensé que je pouvais la limiter aux types de «service» uniquement. Sauf qu'il n'y avait pas de type de «service» commun, donc je ne pouvais le faire qu'avecClass<?>
. Hélas.J'ai trouvé
class<T>
utile lorsque je crée des recherches de registre de service. Par exemplela source
Comme d'autres réponses le soulignent, il existe de nombreuses et bonnes raisons pour lesquelles cela a
class
été rendu générique. Cependant, il y a de nombreuses fois où vous n'avez aucun moyen de connaître le type générique à utiliserClass<T>
. Dans ces cas, vous pouvez simplement ignorer les avertissements d'éclipse jaune ou vous pouvez utiliserClass<?>
... C'est comme ça que je le fais;)la source
@SuppressWarnings("unchecked")
vient à la rescousse! (Faites juste attention à toujours appliquer à la plus petite portée d'un possible car il fait des problèmes potentiels obscurs dans votre code.)Suite à la réponse de @Kire Haglin, un autre exemple de méthodes génériques peut être vu dans le documentation pour JAXB :
Cela permet
unmarshal
de renvoyer un document d'un type d'arbre de contenu JAXB arbitraire.la source
Vous souhaitez souvent utiliser des caractères génériques avec
Class
. Par exemple,Class<? extends JComponent>
vous permettrait de spécifier que la classe est une sous-classe deJComponent
. Si vous avez récupéré l'Class
instance à partir deClass.forName
, vous pouvez utiliserClass.asSubclass
pour effectuer le transtypage avant d'essayer, par exemple, de construire une instance.la source
En java
<T>
signifie classe générique. Une classe générique est une classe qui peut fonctionner sur n'importe quel type de type de données ou en d'autres termes, nous pouvons dire qu'elle est indépendante du type de données.Où T signifie type. Maintenant, lorsque vous créez une instance de cette classe Shape, vous devrez indiquer au compilateur pour quel type de données cela fonctionnera.
Exemple:
Un entier est un type et une chaîne est également un type.
<T>
représente spécifiquement le type générique. Selon Java Docs - Un type générique est une classe ou une interface générique qui est paramétrée sur des types.la source
Juste pour jeter un autre exemple, la version générique de Class (
Class<T>
) permet d'écrire des fonctions génériques telles que celle ci-dessous.la source
C'est déroutant au début. Mais cela aide dans les situations ci-dessous:
la source
Action a = new Action()
?Action
i une interface, c'est queSomeAction
nous essayons d'obtenir une instance de. Nous n'avons que le nom deSomeAction
disponible au moment de l'exécution.Utilisez simplement la classe de boeuf:
la source