9
votes

Comment résoudre le type réel pour un type de retour générique à l'aide de la réflexion?

J'ai une interface forte> avec une méthode avec un type de retour générique strong>, et à l'exécution des cas de classes qui implémentent indirectement cette interface. Maintenant, je veux trouver le type de retour fort> pour chaque implémentation à l'aide de la réflexion.

( mon idée est d'utiliser ce mécanisme pour définir une stratégie à l'aide d'une interface et trouver une stratégie correspondante (type de retour spécifique) sur un ensemble d'implémentations de stratégie au moment de l'exécution, sans avoir à introduire des méthodes d'assistance redondantes qui Exposez le type em>). p>

Pour être plus spécifique, examinons le scénario suivant: p> xxx pré>

au moment de l'exécution, je veux savoir pour Une classe donnée ( persondaoextension.class code>) quel type sera renvoyé pour la méthode GetById (..) code> (attendu: personne.class code> ). P>

Utilisation de la réflexion, je peux trouver quel type générique type code> est renvoyé de cette méthode. Dans ce cas, c'est un typévariable code> (mais pourrait aussi être une classe code> code>, si une classe de la hiérarchie spécifierait un type de retour covariant): p>

private abstract interface DAO<I, E>
private abstract class AbstractDAO<T> extends Object implements DAO<Integer, T> [raw type:DAO<I, E>]
private class PersonDAO extends AbstractDAO<Person> [raw type:AbstractDAO<T>]
private class PersonDAOExtension extends PersonDAO


2 commentaires

Que voulez-vous faire avec le type, une fois que vous le savez? Si vous envisagez d'utiliser instanceOf Opérateur, vous pouvez faire à la place si (PERSON.CLASS.ISAssignAdFrom (Method.getReturnType ())) {...}


Le type de retour (non générique) est un objet, cela reviendrait toujours faux ...


3 Réponses :


0
votes

J'ai déjà eu un problème similaire. Dans ma solution, la classe abstraite avait une méthode nommée

registre de vide statique (classe clazz,? Étend dao daoinstance) .

et dans la classe abstraite J'ai eu une carte qui références stockées aux instances. J'ai utilisé des singletons mais vous pouvez utiliser un multimap si vous avez plusieurs instances. En utilisant cette technique, vous pouvez vous débarrasser de la réflexion et vous aurez un définir de toutes les implémentations que vous avez enregistrées et leurs classes.

Vous pouvez également enregistrer une classe de pojo aussi bien. Si vous avez besoin de plus d'informations: xxx

registre de vide statique (DaoData DaoData,? étend dao daoinstance)

Je sais que Ce n'est pas la meilleure solution mais c'était simple et faire le travail.


2 commentaires

Quel est le type de retour de cette méthode nommée registre?


Je pense que c'était void .



11
votes

J'étais enfin capable de trouver une solution, de recouvrer en super classes et d'interfaces, remplaçant les variables de type avec les arguments de type passés jusqu'à atteindre la classe de base souhaitée: xxx pré>

fonctionne comme un charme: P>

List<DAO<?, ?>> knownDAOs = ...

for (DAO<?, ?> daoImpl : knownDAOs) {
    Type[] types = resolveActualTypeArgs(daoImpl.getClass(), DAO.class);
    boolean canReadPerson = types[1] instanceof Class<?> && Person.class.isAssignableFrom((Class<?>) types[1]);
}



11
votes

J'ai pu déterminer le type de retour générique d'une méthode d'une ligne en une ligne avec Google Guva's Typeoken classe: xxx pré>

Alternativement, si vous souhaitez obtenir le type générique d'une classe (comme vous l'avez fait dans votre Réponse acceptée), plutôt que le type de retour d'une méthode, vous pouvez effectuer les éléments suivants: P>

(new TypeToken<DAO<?, Person>>() {})
        .isSupertypeOf(TypeToken.of(PersonDAOExtension.class))


0 commentaires