使用 static final 声明的数组作为 Java 注释的参数时可能存在错误?

Possible bug when using static final declared arrays as parameter for Java annotations?

我在 Java 中遇到了一个关于注释的奇怪问题。当我使用 static final 声明的数组作为注释值时。我无法使用反射访问它。为什么会这样?使用静态最终声明数组作为 Java 注释的参数时是否可能存在错误?

我正在使用 JDK 1.7,但我正在使用 Eclipse 编译为 1.6。

如下所述,这段代码没有使用javac编译,出现如下错误: AnnotationTest.java:31: error: incompatible types: AnnotationType[] cannot be converted to AnnotationType

这是一个测试代码:

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

enum AnnotationType {
    TYPE_ONE, TYPE_TWO;

    public static final AnnotationType[] ALL_TYPES = { TYPE_ONE, TYPE_TWO };
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface MyAnnotation {
    AnnotationType[] value();
}

public class AnnotationTest {

    @MyAnnotation(AnnotationType.TYPE_ONE)
    public void methodTypeOne() {
    }

    @MyAnnotation(AnnotationType.TYPE_TWO)
    public void methodTypeTwo() {
    }

    // This annotation does not show up.
    @MyAnnotation(AnnotationType.ALL_TYPES)
    public void methodAllTypes() {
    }

    // This one shows up fine.
    @MyAnnotation({ AnnotationType.TYPE_ONE, AnnotationType.TYPE_TWO })
    public void methodAllSingleTypes() {
    }

    public static void main(String[] args) throws Exception {
        Class<?> clazz = AnnotationTest.class;

        for (Method m : clazz.getDeclaredMethods())
            // Doesn't work for getDeclaredAnnotations() as well.
            System.out.println(m.getName() + " -> " + Arrays.toString(m.getAnnotations()));

        // This is what's printed.
        /*
            main -> []
            methodTypeOne -> [@annotation.test.MyAnnotation(value=[TYPE_ONE])]
            methodTypeTwo -> [@annotation.test.MyAnnotation(value=[TYPE_TWO])]
            methodAllTypes -> []
            methodAllSingleTypes -> [@annotation.test.MyAnnotation(value=[TYPE_ONE, TYPE_TWO])]
         */
    }
}

实际上,事实是您的代码不是使用 javac 编译,但它确实使用 Eclipse 编译(至少是 Mars,我用它测试了您的代码)。

编译时出现的错误是:

incompatible types: AnnotationType[] cannot be converted to AnnotationType

行:

@MyAnnotation(AnnotationType.ALL_TYPES)

不使用大括号,因此 Java 为值创建一个包含单个元素的数组:AnnotationType.ALL_TYPES。但是由于 AnnotationType.ALL_TYPES 已经是一个数组,类型不再兼容。

这在 JLS 中有解释 section 9.7.1:

If the element type is an array type, then it is not required to use curly braces to specify the element value of the element-value pair. If the element value is not an ElementValueArrayInitializer, then an array value whose sole element is the element value is associated with the element.