类最终变量不是最终变量

时间:2017-05-22 20:34:25

标签: java

为什么这个变量不被认为是最终的?这段代码没有编译,我会说它是一个bug或至少是奇怪的..

public class QualifierConfiguration {
    public static final String RANK_CALCULATOR = RankCalculatorImpl.class.getName();
}


public class Implementation{
    private final RankCalculator rankCalculator;
    public Implementation(@Qualifier(QualifierConfiguration.RANK_CALCULATOR) RankCalculator rankCalculator){
        this.rankCalculator = rankCalculator;
    }
}

,即使这不起作用

public class QualifierConfiguration {
    public static final String RANK_CALCULATOR = getValue();
    private static String getValue(){
        return "string";
    }
}

2 个答案:

答案 0 :(得分:1)

final变量不一定是编译时常量:

4.12.4. final Variables

  

变量可以声明为final。最终变量只能分配给一次   ...
  常量变量是基本类型或类型String的最终变量,使用常量表达式§15.28)进行初始化。

RankCalculatorImpl.class.getName()不是常量表达式,getValue()也不是。

请注意,对于具有Class值的注释,由于注释的特定规则,允许使用类RankCalculatorImpl.class等类文字,但它们仍然不会生成编译时常量(同样适用)到enum常量引用)。对于原始值和String值,the specification明确要求注释值的常量表达式:

  

当且仅当下列之一为真时,元素类型T才与元素值V相称:
  ...

     
      
  • T不是数组类型,V的类型与T分配兼容(第5.2节),并且:

         
        
    • 如果T是基本类型或String,则V是常量表达式(第15.28节)。
    •   
    • 如果TClass或调用Class(§4.5),则V为类文字(第15.8.2节)。
    •   
    • 如果T是枚举类型(§8.9),则V是枚举常量(§8.9.1)。
    •   
    • V不是null
    •   
  •   

所以在这里,除了将实际限定名称指定为字符串文字之外别无选择:

public static final String RANK_CALCULATOR = "actual.package.name.RankCalculatorImpl";

答案 1 :(得分:0)

您必须将常量表达式传递给注释。所以它必须在编译期间保持不变。您可以获得有关编译时常量here的更多信息。类似的SO问题here

您从中获得的例外是:The value for annotation attribute Qualifier.value must be a constant expression