为什么 null 不是编译时常量?

2022-09-04 01:50:49

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


答案 1

你不是编译时常量,因为JLS它不是。唯一可以在常量表达式中使用的类型是基元类型和 。CONSTANTString

它的意义在于,实例(通常)具有语义上显着的对象标识,可将其与其他实例区分开来。此对象标识不能在类文件中编码...或者至少,它不能用当前的类文件格式进行编码。(如果可以的话,还会有各种各样的其他问题......ObjectObject

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

  • 你不能有作为表达式。nullcase
  • 由于对于引用类型不是常量表达式,因此不能将其用于 Java 的“条件编译”习语,该习语涉及将 具有常量表达式的表达式作为条件。(此外不是一个有用的条件...)==ifnull == null

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

参考:


答案 2

在你的例子中,常量不是编译时常量。

编译时常量是一个常量,其值在编译时已知,它不会进一步更改,然后编译器将代码中所有位置的常量名称替换为其值。

通常,使用 final 声明的基元类型或字符串文本被编译器视为编译时常量。例:

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

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

非编译时常量示例

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

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

这同样适用于静态最终对象常量 = null

符合 JLS 标准

空文本的类型是空类型;其值是空引用。