Comment obtenir des informations de type générique à partir de getAnnotatedParameterTypes() en Java 8 ?
-
21-12-2019 - |
Question
Il semble que getAnnotatedParameterTypes()
renvoie un tableau de AnnotatedType
contient des types bruts plutôt que génériques.Par exemple:
public <T> void genericMethod(T t) {
}
@Test
public void testAnnotatedTypes() throws ReflectiveOperationException {
Method method = getClass().getMethod("genericMethod", Object.class);
Type type = method.getGenericParameterTypes()[0];
assertTrue(type instanceof TypeVariable);
AnnotatedType annotatedType = method.getAnnotatedParameterTypes()[0];
// This fails; annotatedType implements only AnnotatedType
assertTrue(annotatedType instanceof AnnotatedTypeVariable);
// This fails too; type is a TypeVariable while annotatedType.getType() is
// Object.class
assertEquals(type, annotatedType.getType());
}
Quelle est la raison du désaccord avec getGenericParameterTypes()
?
La solution
Il y a un rapport de bug à ce sujet, et cela a depuis été corrigé.
Il y a une différence entre Method#getGenericParameterTypes()
et Method#getAnnotatedParameterTypes()
.
Le premier donne des garanties sur les types qu'il renvoie
Si un type de paramètre formel est un type paramétré, l'objet type renvoyé pour lui doit refléter avec précision les paramètres de type réel utilisés dans le code source.
Si un type de paramètre formel est une variable de type ou un type paramétré, il est créé.Sinon, c'est résolu.
alors que ce dernier ne le fait pas, pas clairement du moins :
Renvoie un tableau de
AnnotatedType
objets qui représentent l'utilisation de types pour spécifier des types de paramètres formels de la méthode / constructeur représenté par ceExecutable
.
Nous devons supposer que getAnnotatedParameterTypes()
renvoie les types effacés (même si cela n'a peut-être pas été prévu ainsi).La variable de type illimitée T
est effacé pour Object
.Si tu avais <T extends Foo>
, il serait effacé pour Foo
.
En ce qui concerne les commentaires sur l'obtention de l'annotation à partir d'un argument de type dans un paramètre de méthode, il n'y a aucun moyen étant donné ce qui précède.On pourrait penser que cela fonctionne comme pour les champs.
public static void main(String[] args) throws Exception {
Field field = Example.class.getField("field");
AnnotatedParameterizedType annotatedParameterizedType = (AnnotatedParameterizedType) field
.getAnnotatedType();
System.out.println(annotatedParameterizedType
.getAnnotatedActualTypeArguments()[0].getType());
System.out.println(Arrays.toString(annotatedParameterizedType
.getAnnotatedActualTypeArguments()[0].getAnnotations()));
}
@Retention(RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE_USE })
@interface Bar {
}
public List<@Bar String> field;
qui imprime
class java.lang.String
[@com.example.Example$Bar()]
Je pense vraiment que c'est un bug qui doit être corrigé et je suivrai le rapport de bug lié ci-dessus.