Java 为什么编译时常量仅限于原语和字符串?

Java 为什么编译时常量仅限于原语和字符串?,java,compiler-optimization,Java,Compiler Optimization,这只是出于好奇,我想我也知道答案,但只是想验证和了解其他观点 说明编译时常量仅限于基元类型和字符串。为什么即使我将某种类型的引用a声明为final(final a aObj=new a();)?是因为类尚未加载还是其他原因?JDK中还有那么多其他的不可变类,为什么不包括这些呢?因为对象(可变或不可变)的构造可能会产生副作用,这些副作用必须在运行时发生。字符串是一个例外,因为Java语言假定这永远不会发生。它也是例外,因为它是Java语言规范所依赖的少数几个类之一;i、 e.在处理文字和某些类型的

这只是出于好奇,我想我也知道答案,但只是想验证和了解其他观点


说明编译时常量仅限于基元类型和字符串。为什么即使我将某种类型的引用
a
声明为
final
final a aObj=new a();
)?是因为类尚未加载还是其他原因?JDK中还有那么多其他的不可变类,为什么不包括这些呢?

因为对象(可变或不可变)的构造可能会产生副作用,这些副作用必须在运行时发生。字符串是一个例外,因为Java语言假定这永远不会发生。它也是例外,因为它是Java语言规范所依赖的少数几个类之一;i、 e.在处理文字和某些类型的
switch
语句(Java 6及更高版本)的语义方面

后者与“编译时常量”特别相关,因为开关臂表达式必须是编译时常量表达式

还有几个其他因素:

  • 对于编译器和运行时JVM来说,编译时常量的处理更为复杂

  • 当以增量方式编译代码时,编译时常量可能会有意外的行为,因此限制这种行为发生的情况是有益的(对于程序员而言)

  • 使更多类型符合编译时常量的条件可能没有多大实际好处


如何使对象成为编译时常量?虚拟机、抖动等将以他们想要的任何方式处理对象创建,那么您将如何使其工作良好?还为它们运行构造函数吗?构造函数可以有只能在运行时执行的自定义代码对象创建本身就是一个运行时进程。字符串(特别是字符串文字)是以特殊方式处理的。它们是在类被加载并添加到字符串常量池时生成的。因此,该值可以作为字节码的一部分进行传递。@SamiKuhmonen:我感到困惑,因为如果字符串可以,那么为什么其他类不能呢?下面Stephen的回答澄清了这是可能的,因为字符串是以特殊的方式处理的。谢谢你的回答,我对字符串的思考就像其他任何类一样,导致了一般化。