Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
103 views
in Technique[技术] by (71.8m points)

java - Why annotation on generic type argument is not visible for nested type?

I don't get the behaviour of following code: https://gist.github.com/tomaszalusky/3e3777b4fd0c6096f3f707bb19b50b52 - see embedded:

import java.lang.reflect.*;
import java.util.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


public class AnnotationOnTypeArgument {

    @Target({ElementType.FIELD,ElementType.PARAMETER,ElementType.METHOD,ElementType.TYPE_USE})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Anno {

    }

    interface Nested<T> {

    }

    Toplevel<@Anno Integer> toplevel;

    Nested<@Anno Integer> nested;

    public static void main(String[] args) throws Exception {
        print(AnnotationOnTypeArgument.class.getDeclaredField("toplevel"));
        print(AnnotationOnTypeArgument.class.getDeclaredField("nested"));
    }

    private static void print(Field field) {
        AnnotatedType annotatedType = field.getAnnotatedType();
        AnnotatedParameterizedType annotatedParameterizedType = (AnnotatedParameterizedType)annotatedType;
        ParameterizedType parameterizedType = (ParameterizedType)annotatedParameterizedType.getType();
        AnnotatedType argType = annotatedParameterizedType.getAnnotatedActualTypeArguments()[0];
        System.out.printf("field %s%ntype=%s%nannotatedType=%s%nannotations=%s%ntype=%s%n%n",
                field.getName(), parameterizedType, argType, Arrays.asList(argType.getDeclaredAnnotations()), argType.getType());
    }

}

interface Toplevel<T> {

}

EDIT: the actual result is:

field toplevel
type=Toplevel<java.lang.Integer>
annotatedType=sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@1540e19d
annotations=[@AnnotationOnTypeArgument$Anno()]
type=class java.lang.Integer

field nested
type=AnnotationOnTypeArgument.AnnotationOnTypeArgument$Nested<java.lang.Integer>
annotatedType=sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@677327b6
annotations=[]
type=class java.lang.Integer

Why the array of declared annotations on type argument is empty when surrounding type is nested? I expect to have one element just as for top level type. I would appreciate any explanation based on JLS.

Happens consistently on JDK8u101 (http://compilejava.net), older JDK8 and Eclipse.

Thanks!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is a bug in the OpenJDK, I have reported this a while ago and I hope it to be fixed. Type annotations are not really used that much in practice and it does not seem a priority. As Holger mentioned, this is a mixup in the implementation of the AnnotatedTypeFactory.

You can use Byte Buddy which parses the class file meta data correctly:

public static void main(String[] args) throws Exception {

    TypeDescription type = TypePool.Default.ofClassPath()
       .describe(AnnotationOnTypeArgument.class.getName())
       .resolve();

    print(type.getDeclaredFields().filter(named("toplevel")).getOnly());
    print(type.getDeclaredFields().filter(named("nested")).getOnly());
}

private static void print(FieldDescription field) {
    System.out.printf("field %s%ntype=%s%nannotations=%s%ntype=%s%n%n",
            field.getName(),
            field.getType(),
            field.getType().getTypeArguments().get(0),
            field.getType().getTypeArguments().get(0).getDeclaredAnnotations());
}

This gives you the expected output:

field toplevel
type=net.bytebuddy.Toplevel<java.lang.Integer>
annotations=class java.lang.Integer
type=[@net.bytebuddy.AnnotationOnTypeArgument$Anno()]

field nested
type=net.bytebuddy.AnnotationOnTypeArgument.net.bytebuddy.AnnotationOnTypeArgument$Nested<java.lang.Integer>
annotations=class java.lang.Integer
type=[@net.bytebuddy.AnnotationOnTypeArgument$Anno()]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...