2011-10-06 5 views
1

J'ai une classe qui a une propriété List<String> ou List<SomeObject>.Propriété de liste générique, obtenir le type de générique

-je obtenir le type de propriété que celle-ci:

propertyClass = PropertyUtils.getPropertyType(currentObject, property);

Ce que je veux faire est de vérifier que le propertyClass est un List<SomeType> et obtenir l'objet de classe pour le type dans la liste. Après cela, je vais vouloir créer un ArrayList du type donné et le remplir avec l'objet de ce type (tous créés dynamiquement, je vais l'utiliser pour charger dynamiquement certaines données d'un fichier).

Y a-t-il une façon de le faire en utilisant la réflexion?

+0

Comment 'List' est-il créé initialement? –

Répondre

7

Les génériques sont effacés après la compilation (en raison de type erasure). Vous ne pouvez donc pas les utiliser lors de l'exécution.

+0

Je ne le savais pas, merci pour l'info. – Razvi

+0

J'ai décidé d'utiliser des tableaux au lieu de listes et je l'ai fait fonctionner correctement comme ça :) – Razvi

0

J'ai un problème similaire et j'ai trouvé une solution qui fonctionne pour moi! Cela peut être fait mais cela peut ne pas être fiable (c'est-à-dire que cela ne fonctionne pas dans toutes les situations). Vous devez d'abord obtenir le "Champ" (via des réflexions). Ensuite, récupérez le "GenericType". Ensuite, essayez de convertir ceci en "ParameterizedType". C'est possible s'il y a un paramètre. Ensuite, obtenez "ActualTypeArguments". Habituellement, ce sont des classes, donc vous pouvez les lancer (sinon vous pouvez essayer Class.forName (...)) et vous avez déjà le type des éléments dans la liste.

Toutefois, ce travail ne marche pas si je fais ceci:

class MyList extends List<String> {... } 

Et puis plus tard:

MyList list = new MyList(); // This would be List<String> 

vous aviez réellement besoin d'inspecter le type pour voir si elle est une liste et si il a un type déclaré dans n'importe quelle classe ou interface. Mais il pourrait y en avoir plus d'un et le type pourrait être lié à plusieurs interfaces, pas seulement à une classe. bien sûr, vous pouvez simplement ignorer les propriétés qui ne sont pas "List" et peut-être jeter une erreur de compilation s'il y en a une (je ferai probablement cela).

Ensuite, il y a le problème avec les caractères génériques: List list = ... Tout ce que vous pouvez faire est de le remplacer par "Object", mais ce n'est pas sûr si vous voulez ajouter des éléments à la liste! (encore une fois, vous pouvez vérifier cela au moment de la compilation et lancer une erreur s'il y a des caractères génériques)

Une autre solution consiste à utiliser une liste vérifiée (voir Collections.checkedList (List, Class)) et essayer d'obtenir ce type à l'exécution (Vous avez probablement besoin de réflexion pour cela). Cela fonctionnerait beaucoup mieux et serait beaucoup plus robuste que les génériques.

0

J'ai trouvé une autre réponse par Bob Lee, Sven Mawson, et Jesse Wilson:

[public class TypeToken:] représente un type générique T. Java ne fournit pas encore un moyen de représenter générique types, donc cette classe fait. Force les clients à créer une sous-classe de cette classe qui permet de récupérer les informations de type même au moment de l'exécution.

Source: http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/reflect/TypeToken.html

Il y avait même un exemple en utilisant List<String> et cela fonctionne vraiment. Le TypeToken aura un rawType de java.util.List et typeArguments est défini sur [java.lang.String]. Il n'y a pas d'effacement de type ici! Cependant, cela ne fonctionne pas pour les caractères génériques tels que List<? extends Foo>.

Notez que c'est un peu différent de l'autre solution que j'ai expliqué dans mon autre réponse. Ici, vous n'analysez pas une propriété sur un bean java pour obtenir les informations de type. Ici vous créez réellement un champ qui stocke les informations de type. Je ne trouve pas de constructeur public ou de méthode d'usine pour créer un TypeToken à partir d'informations de type que vous avez obtenu d'une autre manière. Donc je suppose que ça ne peut vraiment être utilisé que comme une classe interne anonyme vide.

Questions connexes