because annotation and its parameters are resolved at compile time.
1 问题复现
private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
public static final String BEAN_NAME = MyClass.class.getName();
@Bean(name = MyClass.BEAN_NAME)
...
类似问题:
switch(param.getClass().getName()) {
case String.class.getName():
// to do
break;
}
同样以下方式也会出现问题
public static final String PARAM_NAME = String.class.getName();
switch(param.getClass().getName()) {
case PARAM_NAME:
// to do
break;
}
2 常量表达式的定义
§15.28 Constant Expressions
15.28. Constant Expressions
A compile-time
constant expression
is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:
- Literals of primitive type and literals of type
String
- Casts to primitive types and casts to type
String
- […] operators […]
- Parenthesized expressions whose contained expression is a constant expression.
- Simple names that refer to constant variables.
- Qualified names of the form
TypeName
.
Identifier
that refer to constant variables.
No method calls are listed there, so method call result cannot be the constant expression even if the method is trivial. But “Simple names that refer to constant variables” are listed here, so reference to the constant variable is also a constant.
A
static final
field is not necessarily a compile-time constant, even if for practical purposes it’s a constant at runtime.
classObject.getName()
is a method call, and the results of method calls are by definition not compile-time constants. A string literal
is
a compile-time constant.
Note that while many situations could take a
static final
reference as a constant for the lifetime of the program, a
switch
has to have its options hard-coded at compile-time. The value of a
case
target must be either an enum value or a (compile-time)
3 常量使用
常量使用有很多限制, 比如 switch-case 中, 不允许使用 MyEnum.Monday, 而只能是 Monday;
switch(enum) {
case MyEnum.Monday: // 错误
break;
case Monday: // 正确
}
一切的原因都是因为存在 运行时 和 编译时 的区别
switch-case 很好理解, 如果存在 MyEnum.Monday 和 YouEnum.Monday, 都是常量, 但用谁的呢. 既然只能用一个类, 干脆就不让写类名了
ps: Class#getClass() 适用于具有 Class 对象但不知道实际类的代码