47 votes

Que signifie la nature générique de la classe Class<T> ? Qu'est-ce que T ?

Je comprends les génériques quand il s'agit de collections. Mais qu'est-ce que cela signifie dans le cas des Class<T> classe ? Lorsque vous instanciez une Class objet, il n'y a qu'un seul objet. Alors pourquoi le T paramètre ? Que spécifie-t-il ? Et pourquoi est-il nécessaire (s'il l'est) ?

50voto

dasblinkenlight Points 264350

Paramètre de type <T> a été ajouté à java.lang.Class pour permettre un idiome spécifique 1 - l'utilisation de Class comme des fabriques d'objets à sécurité intrinsèque. Essentiellement, l'ajout de <T> vous permet d'instancier des classes d'une manière sûre, comme ceci :

T instance = myClass.newInstance();

Paramètre de type <T> représente la classe elle-même, ce qui vous permet d'éviter les effets désagréables de l'effacement de type en stockant Class<T> dans une classe générique ou en le passant comme paramètre à une méthode générique. Notez que T ne suffirait pas à lui seul à accomplir cette tâche. 2 : le type de T est effacé, il devient donc java.lang.Object sous le capot.

Voici un exemple classique où <T> Le paramètre de la classe devient important. Dans l'exemple ci-dessous, le compilateur Java est capable d'assurer la sécurité de type, vous permettant de produire une collection typée à partir d'une chaîne SQL et d'une instance de Class<T> . Notez que la classe est utilisée comme un usine et que sa sécurité de type peut être vérifiée au moment de la compilation :

public static <T> Collection<T> select(Class<T> c, String sqlStatement) {
    Collection<T> result = new ArrayList<T>();
    /* run sql query using jdbc */
    for ( /* iterate over jdbc results */ ) {
        T item = c.newInstance();
        /* use reflection and set all of item’s fields from sql results */
        result.add(item);
    }
    return result;
}

Étant donné que Java efface le paramètre de type, ce qui en fait une java.lang.Object ou une classe spécifiée en tant que limite supérieure il est important d'avoir accès à la Class<T> à l'intérieur de l'objet select méthode. Puisque newInstance renvoie un objet de type <T> le compilateur peut effectuer une vérification de type, éliminant ainsi un cast.


1 SUN Oracle a publié un bon article expliquant tout cela .
2 Ceci est différent des implémentations de génériques sans effacement de type, comme celle de .NET.
3 Tutoriel Java Generics par Oracle.

8voto

MvG Points 22342

Le site réponse de dasblinkenlight a déjà démontré l'une des principales utilisations de ce paramètre. Il y a un autre aspect que je considère pertinent : en utilisant ce paramètre, vous pouvez restreindre le type de classe que vous voulez passer à un endroit donné. Ainsi, par exemple

Class<? extends Number> cls

signifie que cls peut être n'importe quelle classe implémentant le Number interface. Cela peut aider à détecter certaines erreurs au moment de la compilation et rend les exigences relatives aux arguments de classe plus explicites.

Peut-être qu'une comparaison avec le cas sans génériques s'impose.

// Java ≥5 with generics    // Java <5 style without generics
Class<? extends Foo> c;     Class c;
Foo t1 = c.newInstance();   Foo t1 = (Foo)c.newInstance();
Object obj;                 Object obj;
Foo t2 = c.cast(obj);       Foo t2 = (Foo)c.cast(obj);

Comme vous pouvez le voir, ne pas avoir T comme argument nécessiterait un certain nombre de castings explicites, car les méthodes correspondantes devraient retourner Object au lieu de T . Si Foo est lui-même un argument de type générique, alors tous ces casts ne seraient pas vérifiés, ce qui entraînerait une série d'avertissements du compilateur. Vous pouvez les supprimer, mais le problème principal demeure : le compilateur ne peut pas vérifier la validité de ces casts si vous n'utilisez pas correctement l'argument de type.

1voto

Óscar López Points 97105

En Java, il y a une seule métaclasse : Class . Ses instances (il n'en existe qu'une par type) sont utilisées pour représenter les classes et les interfaces, c'est pourquoi l'élément T en Class<T> fait référence à la type de la classe ou de l'interface que l'instance actuelle de Class représente.

0voto

Eldius Points 104

L'utilisation de génériques dans le type de classe permet de définir le type de la classe. Si j'ai ' Class obj' mon objet obj ne peut contenir que des enfants de Charsequence. C'est un argument optionnel. Je mets souvent un '?' pour éviter les avertissements de l'IDE Eclipse si je n'ai pas besoin d'un type de classe spécifique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X