Java: comment puis-je obtenir une classe littérale à partir d'un type générique?
Généralement, j'ai vu des gens utiliser la classe littéral comme ceci:
Class<Foo> cls = Foo.class;
Mais que faire si le type est générique, par exemple la Liste? Cela fonctionne bien, mais a un avertissement depuis Liste doit être paramétré:
Class<List> cls = List.class
Alors pourquoi ne pas ajouter un <?>
? Eh bien, cela provoque une erreur d'incompatibilité de type:
Class<List<?>> cls = List.class
J'ai pensé à quelque chose comme ça pourrait fonctionner, mais c'est juste une plaine ol' erreur de syntaxe:
Class<List<Foo>> cls = List<Foo>.class
Comment puis-je obtenir un Class<List<Foo>>
statiquement, par exemple, à l'aide de la classe littérale?
Je pourrait utilisation @SuppressWarnings("unchecked")
pour se débarrasser des alertes causées par la non-paramétré utilisation de la Liste dans le premier exemple, Class<List> cls = List.class
, mais je préfère ne pas.
Des suggestions?
Vous devez vous connecter pour publier un commentaire.
Vous ne pouvez pas en raison de type d'effacement.
Java génériques sont un peu plus de sucre syntaxique pour Objet de moulages. Pour le démontrer:
Le seul cas où le type générique de l'information est conservée au moment de l'exécution est avec
Champ.getGenericType()
si l'interroger les membres d'une classe via la réflexion.Tout cela, c'est pourquoi
de l'Objet.getClass()
a cette signature:L'important étant
Class<?>
.Pour le dire d'une autre manière, à partir du Java Génériques FAQ:
List<Integer> list1 = new ArrayList<Integer>(); List<String> list2 = (List<String>)list1; list2.add("foo"); // perfectly legal
Vous le pouvez;t le faire en Java, vous bénéficiez d'incompatibilité de type erreur de compilation !List<String> list2 = (List<String>) (Object) list1;
Il n'y a pas de Classe littéraux de type paramétré, cependant il y a des objets de Type que de bien définir ces types.
Voir java.lang.de réfléchir.ParameterizedType
- http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/ParameterizedType.html
Google Gson bibliothèque définit un TypeToken classe qui permet tout simplement de générer des types paramétrés et l'utilise pour spec objets json avec des complexes de type paramétré dans un générique de manière conviviale. Dans votre exemple, vous utilisez:
J'avais l'intention de poster des liens vers les TypeToken et Gson classes javadoc mais de Débordement de Pile ne me laisse pas poster plus d'un lien depuis, je suis un nouvel utilisateur, vous pouvez les trouver facilement à l'aide de la recherche Google
clzz = new TypeToken<E>(){}.getRawType();
à plus tard itérer sur structurée de la même manière les énumérations avecclzz.getEnumConstants()
et puis, finalement, réfection d'appel états méthodes de laMethod method = clzz.getDeclaredMethod("getSomeFoo");
tellement gagner! Merci!!!!Vous pouvez le gérer avec un double cast :
@SuppressWarnings("unchecked")
Class<List<Foo>> cls = (Class<List<Foo>>)(Object)List.class
Object
àClass
vous pouvez probablement économiser les frais généraux d'un (inutile) vérifié exécution en fonte.Class
au lieu deObject
, comme vous le suggérez, semble de plus en plus significatives, mais elle ne supprime pas la nécessité de la@SuppressWarnings("unchecked")
annotation, il est même possible d'ajouter 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 permet pas de modifier / améliorer tout ça. OP même dit dans sa question qu'il ne veut pas l'utiliserSuppressWarnings
...Pour exposer sur cletus réponse à l'exécution de tous les record des types génériques est supprimé. Les génériques sont traitées uniquement dans le compilateur et sont utilisés pour fournir un type supplémentaire de sécurité. Ils sont vraiment simplement abréviation qui permet au compilateur d'insérer typecasts aux endroits appropriés. Par exemple, auparavant, vous deviez effectuer les opérations suivantes:
devient
Cela permet au compilateur de vérifier votre code à la compilation, mais à l'exécution, il ressemble toujours le premier exemple.
Bien que nous savons tous qu'il est effacée. Mais il ne 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 les récupérer pour:
où il est effacée.
GenericEntity
etGenericType
.En raison de l'exposé fait que la Classe des littéraux n'a pas de type générique de l'information, je pense que vous devriez supposer qu'il sera impossible de se débarrasser de tous les avertissements. D'une certaine manière, à l'aide de
Class<Something>
est la même que l'utilisation d'une collection sans spécifier le type générique. Le mieux que je pouvais sortir avec a:Vous pouvez utiliser une méthode d'aide à se débarrasser de
@SuppressWarnings("unchecked")
toute une classe.Ensuite, vous pouvez écrire
D'autres exemples d'utilisation sont
Cependant, car il est rarement vraiment utile, et l'utilisation de la méthode défaites au compilateur le type de la vérification, je recommande de ne pas mettre en œuvre dans un endroit où il est accessible au public.