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

Muh*_*him 13 java null bytecode

因此,如果我有一个static final Object CONSTANT = null,由于某种原因,如果我在另一段代码中引用doSomething(CONSTANT)它,它将不会在编译期间嵌入到代码中.因此,不是doSomething(null)在编译之后,而是在编译之后doSomething(CONSTANT).

Ste*_*n C 17

CONSTANT不是编译时常量,因为JLS 说它不是.可以在常量表达式中使用的唯一类型是基本类型和String.

它的意义在于Object实例(通常)具有语义上重要的对象标识,以区别于其他Object实例.此对象标识不能在类文件中编码...或者至少,它不能使用当前的类文件格式进行编码.(如果可以,会有各种其他问题......)

这个值null(理论上)可以作为一个特例来处理,除了没有太多意义.具体而言,您不能null在语言学角度要求(或有利)"编译时间常数"的任何上下文中使用.例如:

  • 你不能null作为一个case表达.
  • 由于==引用类型不是常量表达式,因此不能将它用于Java"条件编译"习惯用法,该惯用法涉及if使用常量表达式作为条件.(此外null == null不是一个有用的条件......)

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

参考:

  • 唯一需要编译时 null 的地方是作为 Java 注释的默认值 (2认同)
  • 正确答案实际上只是“因为 JLS 说不是”。其他一些部分有点误导或不正确,例如使用“final String s = null”仍然不会使其成为常量,即使变量的类型是“String”;因为“null”永远不可能是编译时常量。虽然 `null == null` 不能用于条件编译,但可以使用 `"" == ""`,至少在 Java 16 中是这样。 (2认同)