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

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

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

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

使用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 ... } 

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

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

JLS有关于注释的合适参数值的以下内容:

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

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

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

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

我在下面得到了“注释值必须是类文字”:

 @ServerEndpoint(value="/story/notifications", encoders = (StickerEncoder.class), decoders = (StickerDecoder.class)) 

这是在关于websockets的Oracles教程之一时发生的。 原来video不是720p的质量,模糊隐藏了看起来像花括号的大括号。 因此,更改大括号的括号(括号)时错误消失。

 @ServerEndpoint(value="/story/notifications", encoders = {StickerEncoder.class}, decoders = {StickerDecoder.class}) 

任何可能在将来绊倒的人。

看看这个:

 public static final Class TEST_EXCEPTION = RuntimeException.class; 

该类应该是编译器能够检查的Throwable。 所以,试试这个:

 public static final Class TEST_EXCEPTION = RuntimeException.class;