It seems like getAnnotatedParameterTypes() returns an array of AnnotatedTypes holding raw, rather than generic, types.  For example:
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());
}
What's the reason for the disagreement with getGenericParameterTypes()?
You can get around the superfluous reference by providing a generic static factory method. Something like public static <T> GenericClass<T> of(Class<T> type) {...} and then call it as such: GenericClass<String> var = GenericClass. of(String. class) .
The short answer is, that there is no way to find out the runtime type of generic type parameters in Java. A solution to this is to pass the Class of the type parameter into the constructor of the generic type, e.g.
A Generic class simply means that the items or functions in that class can be generalized with the parameter(example T) to specify that we can add any type as a parameter in place of T like Integer, Character, String, Double or any other user-defined type.
There's a bug report about this, and it has since been fixed.
There's a difference between Method#getGenericParameterTypes() and Method#getAnnotatedParameterTypes().
The former makes guarantees about the types it returns
If a formal parameter type is a parameterized type, the Type object returned for it must accurately reflect the actual type parameters used in the source code.
If a formal parameter type is a type variable or a parameterized type, it is created. Otherwise, it is resolved.
while the latter doesn't, not clearly at least:
Returns an array of
AnnotatedTypeobjects that represent the use of types to specify formal parameter types of the method/constructor represented by thisExecutable.
We have to assume that getAnnotatedParameterTypes() returns the erased types (although it may not have been intended that way). The unbounded type variable T is erased to Object. If you had <T extends Foo>, it would be erased to Foo.
As for the comments, about getting the annotation from a type argument in a method parameter, there's no way given the above. One would think it works as it does for fields.
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;
which prints
class java.lang.String
[@com.example.Example$Bar()]
I very much think it's a bug that needs fixing and will be following the bug report linked above.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With