Como obter informações de tipo genérico de getAnnotatedParameterTypes() em Java 8?
-
21-12-2019 - |
Pergunta
Parece que getAnnotatedParameterTypes()
retorna uma matriz de AnnotatedType
está mantendo tipos brutos, em vez de genéricos.Por exemplo:
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());
}
Qual é o motivo do desacordo com getGenericParameterTypes()
?
Solução
Há um relatório de bug sobre isso, e desde então foi corrigido.
Há uma diferença entre Method#getGenericParameterTypes()
e Method#getAnnotatedParameterTypes()
.
O primeiro dá garantias sobre os tipos que retorna
Se um tipo de parâmetro formal for um tipo parametrizado, o objeto Type retornado, pois ele deve refletir com precisão os parâmetros de tipo reais usado no código-fonte.
Se um tipo de parâmetro formal for uma variável de tipo ou um tipo parametrizado, ele é criado.Caso contrário, está resolvido.
enquanto o último não, pelo menos não claramente:
Retorna uma matriz de
AnnotatedType
objetos que representam o uso de tipos para especificar tipos de parâmetros formais do método/construtor representado por esteExecutable
.
Temos que assumir que getAnnotatedParameterTypes()
retorna os tipos apagados (embora possa não ter sido planejado dessa forma).A variável de tipo ilimitada T
é apagado para Object
.Se você tinha <T extends Foo>
, seria apagado para Foo
.
Quanto aos comentários, sobre como obter a anotação de um argumento de tipo em um parâmetro de método, não há como fornecer o que foi dito acima.Alguém poderia pensar que funciona como funciona para os campos.
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;
que imprime
class java.lang.String
[@com.example.Example$Bar()]
Eu realmente acho que é um bug que precisa ser corrigido e seguirei o relatório de bug no link acima.