注解无法使用常量 [Attribute value must be constant]

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 对象但不知道实际类的代码

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值