Как получить информацию об общем типе из getAnnotatedParameterTypes() в Java 8?
-
21-12-2019 - |
Вопрос
Это похоже на getAnnotatedParameterTypes()
возвращает массив из AnnotatedType
s содержит необработанные, а не универсальные типы.Например:
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());
}
В чем причина разногласий с getGenericParameterTypes()
?
Решение
Там есть сообщение об ошибке по этому поводу, и с тех пор это было исправлено.
Есть разница между Method#getGenericParameterTypes()
и Method#getAnnotatedParameterTypes()
.
Первый дает гарантии относительно типов, которые он возвращает
Если тип формального параметра является параметризованным типом, возвращаемый для него объект Type должен точно отражать фактические параметры типа , используемые в исходном коде.
Если формальный тип параметра является переменной типа или параметризованным типом, он создается.В противном случае проблема решается.
в то время как последнее этого не делает, по крайней мере, неясно:
Возвращает массив из
AnnotatedType
объекты, представляющие использование типов для указания формальных типов параметров метода/конструктора , представленных этимExecutable
.
Мы должны предположить, что getAnnotatedParameterTypes()
возвращает удаленные типы (хотя, возможно, это не было задумано таким образом).Переменная неограниченного типа T
стирается до Object
.Если бы у вас было <T extends Foo>
, это было бы стерто до Foo
.
Что касается комментариев о получении аннотации из аргумента типа в параметре метода, то вышеописанного способа нет.Можно было бы подумать, что это работает так же, как и для полей.
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;
который печатает
class java.lang.String
[@com.example.Example$Bar()]
Я очень думаю, что это ошибка, которую необходимо исправить, и буду следить за отчетом об ошибке, приведенным выше.