Comment puis-je atteindre cet objectif?
public class GenericClass<T>
{
public Type getMyType()
{
//How do I return the type of T?
}
}
Tout ce que j'ai essayé jusqu'à présent renvoie toujours le type Object
plutôt que le type spécifique utilisé.
java
generics
reflection
Glenn
la source
la source
Réponses:
Comme d'autres l'ont mentionné, cela n'est possible que par réflexion dans certaines circonstances.
Si vous avez vraiment besoin du type, voici le modèle de contournement habituel (sans danger pour le type):
la source
Foo foo1 = GetDao<Foo>(Foo.class).get(Foo.class, 1)
public static <T> GenericClass<T> of(Class<T> type) {...}
puis l' appeler comme tel:GenericClass<String> var = GenericClass.of(String.class)
. Un peu mieux.J'ai vu quelque chose comme ça
dans l' exemple hibernate GenericDataAccessObjects
la source
class A implements Comparable<String>
, le paramètre de type réel estString
, mais il NE PEUT PAS dire que dansSet<String> a = new TreeSet<String>()
, le paramètre de type réel estString
. En fait, les informations sur les paramètres de type sont "effacées" après la compilation, comme expliqué dans d'autres réponses.java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
pour cette réponse.Class-Mate
les gens de Jackson. J'ai écrit un résumé(Class<T>) ((ParameterizedType)getClass().getSuperclass().getGenericSuperclass()).getActualTypeArguments()
pour obtenir des arguments de type réels.Les génériques ne sont pas réifiés au moment de l'exécution. Cela signifie que les informations ne sont pas présentes au moment de l'exécution.
Ajouter des génériques à Java tout en conservant la compatibilité descendante était un tour de force (vous pouvez voir le document fondateur à ce sujet: Rendre l'avenir sûr pour le passé: ajouter de la généricité au langage de programmation Java ).
Il existe une riche littérature sur le sujet, et certaines personnes ne sont pas satisfaites de l'état actuel, certaines disent qu'en fait c'est un leurre et qu'il n'y en a pas vraiment besoin. Vous pouvez lire les deux liens, je les ai trouvés assez intéressants.
la source
Utilisez la goyave.
Un retour while, j'ai posté quelques exemples Fledge complet , y compris les classes abstraites et les sous - classes ici .
Remarque: cela nécessite que vous instanciez une sous - classe de
GenericClass
afin qu'elle puisse lier correctement le paramètre type. Sinon, il retournera simplement le type commeT
.la source
java.lang.IllegalArgumentException: class com.google.common.reflect.TypeToken isn't parameterized
. J'ai donc changé la lignenew TypeToken(getClass()) { }
ennew TypeToken<T>(getClass()) { }
. Maintenant, le code fonctionne bien, mais le type est toujours «T». Voir ceci: gist.github.com/m-manu/9cda9d8f9d53bead2035default Type getParameterType() { final TypeToken<T> typeToken = new TypeToken<T>(getClass()) {}; final Type type = typeToken.getType(); return type; }
GenericClass
, vous devez rendre cette classeabstract
afin qu'une mauvaise utilisation ne se compile pas.Sûr que vous pouvez.
Java n'utilise l'information au moment de l' exécution, pour des raisons de compatibilité ascendante. Mais l'information est effectivement présente sous forme de métadonnées et sont accessibles via la réflexion (mais elles ne sont toujours pas utilisées pour la vérification de type).
Depuis l'API officielle:
http://download.oracle.com/javase/6/docs/api/java/lang/reflect/ParameterizedType.html#getActualTypeArguments%28%29
Cependant , pour votre scénario, je n'utiliserais pas la réflexion. Personnellement, je suis plus enclin à l'utiliser pour le code cadre. Dans votre cas, je voudrais simplement ajouter le type comme paramètre constructeur.
la source
Les génériques Java sont principalement au moment de la compilation, ce qui signifie que les informations de type sont perdues lors de l'exécution.
sera compilé en quelque chose comme
Pour obtenir les informations de type lors de l'exécution, vous devez les ajouter comme argument du ctor.
Exemple:
la source
private final Class<T> type;
Type t = //String[]
la source
J'ai utilisé l'approche suivante:
la source
Je ne pense pas que vous puissiez le faire, Java utilise l'effacement des types lors de la compilation afin que votre code soit compatible avec les applications et les bibliothèques qui ont été créées pré-génériques.
Depuis Oracle Docs:
http://docs.oracle.com/javase/tutorial/java/generics/erasure.html
la source
Technique décrite dans cet article par Ian Robertson fonctionne pour moi.
En bref exemple rapide et sale:
la source
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Je pense qu'il existe une autre solution élégante.
Ce que vous voulez faire, c'est (en toute sécurité) "passer" le type du paramètre de type générique de la classe concerete à la superclasse.
Si vous vous autorisez à considérer le type de classe comme des "métadonnées" sur la classe, cela suggère la méthode Java pour encoder les métadonnées à l'exécution: les annotations.
Définissez d'abord une annotation personnalisée le long de ces lignes:
Vous pouvez alors devoir ajouter l'annotation à votre sous-classe.
Ensuite, vous pouvez utiliser ce code pour obtenir le type de classe dans votre classe de base:
Certaines limites de cette approche sont:
PassedGenericType
) à DEUX endroits plutôt que celui qui n'est pas SEC.la source
Voici ma solution:
la source
Voici une solution de travail !!!
REMARQUES: Peut être utilisé uniquement en tant que superclasse
1. Doit être étendu avec la classe typée (
Child extends Generic<Integer>
)OU
2. Doit être créé en tant qu'implémentation anonyme (
new Generic<Integer>() {};
)la source
Tu ne peux pas. Si vous ajoutez une variable membre de type T à la classe (vous n'avez même pas besoin de l'initialiser), vous pouvez l'utiliser pour récupérer le type.
la source
Voici une façon, que j'ai dû utiliser une ou deux fois:
De même que
la source
Une solution simple pour cette cabine comme ci-dessous
la source
Pour compléter certaines des réponses ici, j'ai dû obtenir le ParametrizedType de MyGenericClass, quelle que soit la hauteur de la hiérarchie, à l'aide de la récursivité:
la source
Voici mon astuce:
la source
T
s'agit d'une variable de type. Dans le cas où ilT
s'agit d'une variable de type, le varargs crée un tableau d'effacement deT
. Voir par exemple http://ideone.com/DIPNwd .Juste au cas où vous utilisez stocker une variable en utilisant le type générique, vous pouvez facilement résoudre ce problème en ajoutant une méthode getClassType comme suit:
J'utilise l'objet de classe fourni plus tard pour vérifier s'il s'agit d'une instance d'une classe donnée, comme suit:
la source
value
estnull
? Deuxièmement, que faire sivalue
est une sous-classe deT
?Constant<Number> c = new Constant<Number>(new Integer(0)); Class<Number> n = c.getClassType();
retourneInteger.class
quand il devrait revenirNumber.class
. Il serait plus correct de revenirClass<? extends T>
.Integer.class
est unClass<? extends Number>
mais pas unClass<Number>
.Voici ma solution
Quel que soit le niveau de votre hiérarchie de classes, cette solution fonctionne toujours, par exemple:
Dans ce cas, getMyType () = java.lang.String
la source
Exception in thread "main" java.lang.NullPointerException at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.findTypeArguments(Main.java:54) at Main$ClassA.<init>(Main.java:43) at Main.main(Main.java:61)
la source
Voici ma solution. Les exemples devraient l'expliquer. La seule exigence est qu'une sous-classe doit définir le type générique, pas un objet.
la source
J'ai fait la même chose que @Moesio Above mais dans Kotlin, cela pourrait être fait de cette façon:
la source
Cela pourrait être utile à quelqu'un. Vous pouvez utiliser java.lang.ref.WeakReference; par ici:
la source
WeakReference
? Veuillez fournir quelques explications avec votre réponse, pas seulement du code.SomeClass<MyClass>
vous pouvez instancierSomeClass
et appelergetType
cette instance et avoir le temps d'exécutionMyClass
.WeakReference
? Ce que vous avez dit n'est pas différent de la plupart des autres réponses.AtomicReference
,List
,Set
).J'ai trouvé que c'était une solution simple, compréhensible et facilement explicable
la source
(T...t)
. (C'est pourquoi ce code ne fonctionne pas.)