Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are annotations on a type parameter accessible in runtime?

Java 8 allows things like:

public List<@NonNull String> names;

But is there a way to access this annotation in runtime or is it available only to compiler plugins?

There's new Method#getAnnotatedReturnType that provides access to annotations on the return type, so I was hoping ParameterizedType would now have something like getActualAnnotatedTypeArguments that would do the same for generic type arguments, but it doesn't exist...

like image 686
kaqqao Avatar asked Mar 12 '23 15:03

kaqqao


2 Answers

The new API continues the tradition of requiring lots of instanceofs and type casts:

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.stream.*;

public class AnnoTest {
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE_USE)
    @interface NonNull {}

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE_USE)
    @interface NonEmpty {}

    List<@NonNull String> list;
    Map<@NonNull Integer, @NonNull @NonEmpty Set<String>> map;
    Object plain;

    public static void main(String[] args) throws ReflectiveOperationException {
        for(Field field: AnnoTest.class.getDeclaredFields()) {
            AnnotatedType at = field.getAnnotatedType();
            System.out.println(formatType(at)+" "+field.getName());
        }
    }
    static CharSequence formatType(AnnotatedType type) {
        StringBuilder sb=new StringBuilder();
        for(Annotation a: type.getAnnotations()) sb.append(a).append(' ');
        if(type instanceof AnnotatedParameterizedType) {
            AnnotatedParameterizedType apt=(AnnotatedParameterizedType)type;
            sb.append(((ParameterizedType)type.getType()).getRawType().getTypeName());
            sb.append(Stream.of(apt.getAnnotatedActualTypeArguments())
                .map(AnnoTest::formatType).collect(Collectors.joining(",", "<", ">")));
        }
        else sb.append(type.getType().getTypeName());
        return sb;
    }
}

See also the end of this answer for an example handling the other scenarios like type variables, wild card types and arrays.

like image 119
Holger Avatar answered Mar 23 '23 23:03

Holger


There is indeed a method getAnnotatedActualTypeArguments but in AnnotatedParameterizedType, not in ParameterizedType where I was looking for it.

like image 43
kaqqao Avatar answered Mar 23 '23 23:03

kaqqao