14

因此,如果我有static final Object CONSTANT = null, 出于某种原因,如果我在另一段代码中引用它,例如doSomething(CONSTANT),它将不会在编译期间内联到代码中。所以不是doSomething(null)在编译之后,而是doSomething(CONSTANT).

4

2 回答 2

17

CONSTANT不是一个编译时间常数,因为 JLS说它不是。可以在常量表达式中使用的唯一类型是原始类型和String.

它的意义是一个Object实例(通常)具有一个语义上重要的对象身份,将它与其他Object实例区分开来。这个对象标识不能在类文件中编码……或者至少,它不能用当前的类文件格式编码。(如果可以的话,会有各种各样的其他问题......)

该值null(理论上)可以作为特殊情况处理,只是没有太多意义。具体来说,从语言的角度来看,您不能null在需要(或有利)“编译时间常数”的任何上下文中使用。例如:

  • 你不能null作为一种case表达方式。
  • 由于==for 引用类型不是常量表达式,因此您不能将它用于涉及if以常量表达式作为条件的 Java“条件编译”习语。(而且除此之外null == null不是一个有用的条件......)

就内联而言,虽然不能在字节码中内联“常量”(因为 JLS 关于什么是“常量表达式”的规则),但 JIT 编译器的优化器将被允许这样做,并且实际上可能会这样做...如果有切实的性能优势。

参考:

于 2013-07-20T05:54:52.107 回答
4

在您的情况下,CONSTANT不是编译时间常数。

编译时常量是一个常量,它的值在编译时是已知的,不会进一步改变,然后编译器会用它的值替换代码中各处的常量名。

通常,使用 final 声明的原始类型或字符串文字被编译器视为编译时间常量。例子:

final int a=10;
final String constant =”this is compile time const”;

这些都是编译时常量,我们可以在 switch 语句的 case 标签中使用编译时常量表达式

非编译时常量的示例

final String xyz = new String(”this is not a compile time const");

这里 xyz 字符串对象不是编译时常量。因为这个“xyz”字符串对象将在运行时创建,而这里编译器只知道引用而不知道字符串对象。

这同样适用于您的静态最终对象 CONSTANT = null

根据JLS

空字面量的类型是空类型;它的值是空引用。

于 2013-07-20T20:54:21.607 回答