有人可以解释为什么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常量,但只接受类文字?
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中.