En règle générale, j'ai vu des gens utiliser le littéral de classe comme ceci:
Class<Foo> cls = Foo.class;
Mais que faire si le type est générique, par exemple List? Cela fonctionne bien, mais comporte un avertissement car List doit être paramétré:
Class<List> cls = List.class
Alors pourquoi ne pas en ajouter un <?>
? Eh bien, cela provoque une erreur de non-correspondance de type:
Class<List<?>> cls = List.class
J'ai pensé que quelque chose comme ça fonctionnerait, mais ce n'est qu'une simple erreur de syntaxe:
Class<List<Foo>> cls = List<Foo>.class
Comment puis-je obtenir un Class<List<Foo>>
statique, par exemple en utilisant le littéral de classe?
Je pourrais utiliser @SuppressWarnings("unchecked")
pour me débarrasser des avertissements causés par l'utilisation non paramétrée de List dans le premier exemple Class<List> cls = List.class
, mais je préfère ne pas.
Aucune suggestion?
List<Integer> list1 = new ArrayList<Integer>(); List<String> list2 = (List<String>)list1; list2.add("foo"); // perfectly legal
Vous ne pouvez pas le faire en Java, vous obtenez une erreur de compilation de non-concordance de type!List<String> list2 = (List<String>) (Object) list1;
Il n'y a pas de littéraux de classe pour les types paramétrés, mais il existe des objets Type qui définissent correctement ces types.
Voir java.lang.reflect.ParameterizedType - http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/ParameterizedType.html
La bibliothèque Gson de Google définit une classe TypeToken qui permet de générer simplement des types paramétrés et l'utilise pour spécifier des objets json avec des types paramétrés complexes de manière générique. Dans votre exemple, vous utiliseriez:
J'avais l'intention de publier des liens vers les classes TypeToken et Gson javadoc mais Stack Overflow ne me permettra pas de publier plus d'un lien car je suis un nouvel utilisateur, vous pouvez facilement les trouver en utilisant la recherche Google
la source
clzz = new TypeToken<E>(){}.getRawType();
pour itérer plus tard sur des énumérations structurées de manière similaireclzz.getEnumConstants()
et enfin utiliser la réflexion pour appeler les méthodes membres à laMethod method = clzz.getDeclaredMethod("getSomeFoo");
victoire! Merci!Vous pouvez le gérer avec une double distribution:
@SuppressWarnings("unchecked") Class<List<Foo>> cls = (Class<List<Foo>>)(Object)List.class
la source
Object
enClass
vous pouvez probablement économiser les frais généraux d'une distribution d'exécution vérifiée (inutile).Class
au lieu deObject
, comme vous le suggérez, semble plus significatif mais cela ne supprime pas la nécessité de l'@SuppressWarnings("unchecked")
annotation, il ajoute même un nouvel avertissement:Class is a raw type. References to generic type Class<T> should be parameterized
Class<?>
:(Class<List<Foo>>)(Class<?>)List.class
unchecked
avertissement. Cette réponse ne change / améliore rien de tout cela. OP déclare même dans sa question qu'il ne veut pas utiliserSuppressWarnings
...Pour expliquer la réponse de Cletus, au moment de l'exécution, tous les enregistrements des types génériques sont supprimés. Les génériques sont traités uniquement dans le compilateur et sont utilisés pour fournir une sécurité de type supplémentaire. Ce sont vraiment des raccourcis qui permettent au compilateur d'insérer des typecasts aux endroits appropriés. Par exemple, auparavant, vous devez effectuer les opérations suivantes:
devient
Cela permet au compilateur de vérifier votre code au moment de la compilation, mais à l'exécution, il ressemble toujours au premier exemple.
la source
Le Java Generics FAQ et donc Cletus' réponse du son comme il est inutile d'avoir
Class<List<T>>
, mais le vrai problème est que cela est extrêmement dangereux:Les
cast()
fait regarder comme s'il est sûr, mais en réalité il n'est pas sûr du tout.Bien que je n'arrive pas là où il ne peut pas y avoir
List<?>.class
=Class<List<?>>
car cela serait très utile lorsque vous avez une méthode qui détermine le type en fonction du type générique d'unClass
argument.Car
getClass()
il y a JDK-6184881 demandant de passer à l'utilisation de caractères génériques, mais il ne semble pas que ce changement sera effectué (très bientôt) car il n'est pas compatible avec le code précédent (voir ce commentaire ).la source
Eh bien, comme nous le savons tous, il est effacé. Mais il peut être connu dans certaines circonstances où le type est explicitement mentionné dans la hiérarchie des classes:
Et maintenant, vous pouvez faire des choses comme:
Plus d'infos ici . Mais encore une fois, il est presque impossible de récupérer pour:
où il est effacé.
la source
GenericEntity
etGenericType
.En raison du fait exposé que les littéraux de classe n'ont pas d'informations de type générique, je pense que vous devriez supposer qu'il sera impossible de se débarrasser de tous les avertissements. D'une certaine manière, l'utilisation
Class<Something>
est identique à l'utilisation d'une collection sans spécifier le type générique. Le mieux que j'ai pu en tirer était:la source
Vous pouvez utiliser une méthode d'aide pour vous débarrasser de
@SuppressWarnings("unchecked")
tout dans une classe.Ensuite, vous pourriez écrire
D'autres exemples d'utilisation sont
Cependant, comme elle est rarement vraiment utile et que l'utilisation de la méthode défait la vérification de type du compilateur, je ne recommanderais pas de l'implémenter dans un endroit où elle est accessible au public.
la source