8
votes

Comment obtenir la classe d'éléments de la liste contenant?

J'ai une liste comme celle-là:

 Field genericField = Wrapper.class.getDeclaredField("myList");
 ParameterizedType genericType = (ParameterizedType) genericField.getGenericType();
 Class<?> genericClass = (Class<?>) genericType.getActualTypeArguments()[0];


6 commentaires

Dupliqué possible: Stackoverflow.com/ Questions / 1942644 / ...


@oers je pense que cette question diffère de votre part suggérée. Parce que j'utilise t et cela fait tout différent.


@Kamaci: Il n'est pas clair de votre question si T est censé être un espace réservé pour une classe de béton ou un paramètre de type de la classe enfermante. Dans ce dernier cas, les réponses qui disent que c'est impossible sont réellement correctes.


@Kamaci: Ah, oui c'est différent. (Il serait bon de fournir le contexte de code plus large.) Et non, il n'y a aucun moyen de le faire.


@Michaelborgwardt j'ai essayé de l'expliquer. T est un espace réservé ici et j'instire ma classe, donc t tient quelque chose mais après cela, je pense qu'il disparaît.


@Kamaci: Oui, ces informations sont effacées, il n'y a aucun moyen de l'obtenir sans changer le code spécifiquement pour la préserver.


4 Réponses :


0
votes

Ceci n'est possible que si la liste, comme indiqué dans votre exemple, est un champ et que le paramètre de type est concret plutôt qu'être un paramètre de type de la classe jointe (ce qui semble être le cas dans votre exemple) et Vous ne pouvez obtenir que le paramètre de type déclaré pour le champ via la réflexion: xxx

Je ne sais pas si cela est tout à fait correct, mais vous obtenez l'idée - c'est plutôt complexe car les paramètres de type peuvent être délimités et des caractères génériques. .


2 commentaires

Cela ne fonctionnera pas réellement si le type est t telle qu'elle est ci-dessus. Il ne fonctionnera que si le type de paramètre est une classe réelle comme Liste


@Peterlawrey tu as eu le point. Cela ne fonctionne pas à cause de t



14
votes

Vous ne pouvez pas en raison de l'effacement de type. Le type générique n'est pas connu au moment de l'exécution (c'est «effacé»), il est utilisé uniquement au moment de la compilation.

C'est une différence majeure entre les génériques Java et les génériques C # par exemple.


0 commentaires

2
votes

vous ne pouvez pas. Cette information n'est pas disponible au moment de l'exécution. Si votre liste n'est pas vide, vous pourriez être capable de vous éloigner de la vérification de la classe du premier élément.


2 commentaires

Les informations réellement sont disponibles disponibles au moment de l'exécution car le mot clé privé indique que c'est un champ.


@Michaelborgwardt, le type de paramètre est t que vous ne pouvez pas lancer dans une classe



6
votes

Pourquoi avez-vous besoin de savoir cela? Peut-être que cela fera ce que vous avez besoin

List list = new ArrayList<Integer>() { }; // create a specific sub-class
final Class<? extends List> listClass = list.getClass();
final ParameterizedType genericSuperclass = (ParameterizedType) listClass.getGenericSuperclass();
Class elementType = (Class) genericSuperclass.getActualTypeArguments()[0];
  • stocker le type dans un champ et ajoutez une méthode getter pour cela. LI> ul>

    comme p> xxx pré>

    • Utilisez getGenerictype () sur le champ actuel, en supposant que le type de paramètre n'est pas générique. LI>
    • Utilisez une sous-classe avec un type spécifique. LI> ul>

      comme p> xxx pré>

      Ceci a le désavantage que vous pouvez finir par créer de nombreuses classes anonymes et une confusion potentielle avec des éléments tels que ArrayList. Classe! = list.getclass () Code> Toutefois Instance de liste de la liste code> p> p>


10 commentaires

Vous pouvez créer un sous-type anonyme de la classe qui contient ce champ.


@Kamaci: Le premier fait, mais il faudrait que votre classe environnante prendrait un paramètre Class dans son constructeur.


La variable de type doit être initialisée?


@Michaelborgwardt je ne veux pas envoyer de paramètre au constructeur de classe wrapper en raison de mes limites


Comme le souligne Michaelborgwardt, il doit être installé dans le constructeur.


@kamaci, pouvez-vous utiliser le wrapper enveloppe = nouveau wrapper () {}; approche?


@Peterlawrey merci de répondre. Juste pour être sûr: je ne peux pas envoyer de parapéter au constructeur, mais je peux changer le code à l'intérieur du constructeur. Alors cela signifie-t-il que je ne pourrai pas le faire à cause de je ne peux pas envoyer de paramètre?


@kamaci, pas à moins que vous ne créez une sous-classe comme je l'ai suggéré (deux fois)


@Peterlawrey désolé mais je ne pouvais pas comprendre ce que tu veux dire. Je n'ai pas compris comment initialiser cette variable de type.


@Kamaci, si vous utilisez une sous-classe, il n'y a pas de variable de type. Cependant, vous devez changer tous les appelants que je soupçonne que vous ne pouvez pas faire (ou vous allez simplement ajouter un paramètre)