注释属性必须是类文字?为什么?常数也应该没问题

sib*_*iba 10 java testng jls

有人可以解释为什么String和Class注释参数的预期不同吗?为什么编译器需要Classes的文字,wherby也接受字符串的常量?

使用Spring的@RequestMapping的工作示例:

public class MyController {
    public static final String REQUEST_MAPPING = "/index.html";
    @RequestMapping(MyController.REQUEST_MAPPING) // ALL OK!
    ...
}
Run Code Online (Sandbox Code Playgroud)

使用TestNG的@Test的WTF示例:

public class MyControllerTest {
    public static final Class TEST_EXCEPTION = RuntimeException.class;
    @Test(expectedExceptions = MyControllerTest.TEST_EXCEPTION) // compilation error, WTF:
    // The value for annotation attribute Test.expectedExceptions must be a class literal
    ...
}
Run Code Online (Sandbox Code Playgroud)

什么工作当然是@Test(expectedExceptions = RuntimeException.class).但为什么?我看到的注释参数的唯一区别是它的类型:String vs Class.为什么Java编译器也接受String常量,但只接受类文字?

Luk*_*ard 8

Java语言规范不允许您使用参数类型的编译时常量Class.您只能使用类文字.

JLS有以下要说一下注解合适的参数值:

当且仅当满足下列条件之一时,元素类型T才与元素值V相称:

  • T是一个数组类型E [],并且:
    • V是一个ElementValueArrayInitializer并且每个ElementValueInitializer在(类似于变量初始值设定在数组初始化)V是相称Ë.要么
    • V是与T相称的ElementValue.
  • V的类型与T分配兼容(第5.2节),此外:
    • 如果T是基本类型或String,则V是常量表达式(第15.28节).
    • V不为空.
    • 如果T是Class,或者是Class的调用,则V是类文字(第15.8.2节).
    • 如果T是枚举类型,则V是枚举常量.

如果元素类型与ElementValue不相称,则为编译时错误.

但是,我不能说为什么这个限制在JLS中.