java 8:class.getName()和String literal之间的区别

时间:2015-11-11 08:11:35

标签: java switch-statement java-8 constants string-literals

我正在研究开关盒。

如果我们使用class.getName(),那么我得到的错误是“case表达式必须是常量表达式”,如下所示:

[<TestCase("1|2|3", 4, 5, 6)>]
let ``My Test``(param1: string, param2: int, param3: int, param4: int) =
    let stringArray = param1.Split('|', SplitStringOptions.None)
    let intArray = Array.map int stringArray

    // My test code

即使我们执行了以下操作,也请在常量中获取字符串类名,然后获取相同的错误:

switch(param.getClass().getName())
    {
        case String.class.getName():
            // to do
            break;
    }

但是,如果我这样做,请使用字符串文字“java.lang.String”,没有错误:

public static final String PARAM_NAME = String.class.getName();
switch(param.getClass().getName())
    {
        case PARAM_NAME:
            // to do
            break;
    }

有人可以解释一下,为什么不采取前两个案件并采取最后一个案例?提前谢谢。

3 个答案:

答案 0 :(得分:8)

classObject.getName()是一个方法调用,根据定义,方法调用的结果不是编译时常量。字符串文字编译时常量。

请注意,虽然许多情况可能会将static final引用作为程序生命周期的常量,但switch必须在编译时对其选项进行硬编码。 case目标的值必须是枚举值或(编译时)ConstantExpression

答案 1 :(得分:6)

每个案例标签必须是&#34;常量表达式&#34;。什么是&#34;常量表达&#34;在Java语言标准中定义,§15.28 Constant Expressions

  

编译时常量表达式是表示基本类型值的表达式或不突然完成的字符串,仅使用以下内容组成:

     
      
  • 原始类型的文字和String类型的文字
  •   
     

...

     
      
  • 引用常量变量的简单名称
  •   

那里没有列出任何方法调用,因此即使方法很简单,方法调用结果也不能是常量表达式。但是&#34;引用常量变量的简单名称&#34;这里列出了,所以对常量变量的引用也是常量。

答案 2 :(得分:4)

这不起作用的原因是要打开的case的值需要在编译时知道(因为它在字节码中是硬编码和内联的)。

String.class.getName()是一个在运行时进行评估的方法调用。是的,static final保证在最初加载类后它不会改变。但是编译时间之后的所有时间都很长。

编译器永远不会调用来自应用程序源代码的任何代码(注释处理除外)。它只编译它。