Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vue.js/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java语言规范Java SE 11版(JLS SE 11)中对常量折叠的描述在哪里?_Java_Java 11_Jls_Compile Time Constant_Constantfolding - Fatal编程技术网

Java语言规范Java SE 11版(JLS SE 11)中对常量折叠的描述在哪里?

Java语言规范Java SE 11版(JLS SE 11)中对常量折叠的描述在哪里?,java,java-11,jls,compile-time-constant,constantfolding,Java,Java 11,Jls,Compile Time Constant,Constantfolding,据我所知,Java在编译时通过常量折叠处理常量变量。我已经尽了最大努力,但我无法从JLS中找到它的描述。有谁能告诉我在哪里可以找到Java 11的常量折叠过程的官方描述吗?Java语言规范定义了语言的语义;常量折叠是一种编译器优化,它不会改变Java程序的行为,因此JLS中没有指定,也不需要指定。允许Java实现不这样做,或者在某些情况下不这样做,但在其他情况下不这样做,只要编译的程序按照JLS的要求执行 也就是说,JLS确实以这样一种方式定义了语言语义,即允许在更多情况下不断折叠,而不改变程序

据我所知,Java在编译时通过常量折叠处理常量变量。我已经尽了最大努力,但我无法从JLS中找到它的描述。有谁能告诉我在哪里可以找到Java 11的常量折叠过程的官方描述吗?

Java语言规范定义了语言的语义;常量折叠是一种编译器优化,它不会改变Java程序的行为,因此JLS中没有指定,也不需要指定。允许Java实现不这样做,或者在某些情况下不这样做,但在其他情况下不这样做,只要编译的程序按照JLS的要求执行

也就是说,JLS确实以这样一种方式定义了语言语义,即允许在更多情况下不断折叠,而不改变程序的行为。最相关的段落可能是您在以下章节中提到的:

常量变量是原语类型或字符串类型的最终变量,用常量表达式§15.28初始化。变量是否为常量变量可能会影响类别初始化§12.4.1、二进制兼容性§13.1、可达性§14.21和明确分配§16.1.1


关于类初始化、二进制兼容性、可达性和确定赋值的参考章节专门定义了常量变量的语义,与其他变量不同;具体地说,它们定义的行为是您期望从折叠常量的编译器中获得的行为。这使得实施规范的人员能够在不过度限制其优化方式的情况下进行优化。

字段的流程从问题中链接的页面链接:

必须删除对常量变量§4.12.4字段的引用 在编译时解析为常数表示的值V 变量的初始值设定项

如果这样一个字段是静态的,那么不应该引用该字段 存在于二进制文件的代码中,包括类或接口 它声明了该字段。这样一个字段必须始终显示为 已初始化§12.4.2;字段的默认初始值,如果 绝不能观察到与V不同的情况

如果这样的字段是非静态的,则不应引用该字段 以二进制文件的形式出现在代码中,类中除外 包含字段的。它将是一个类而不是一个接口, 因为接口只有静态字段。类应该有代码 在实例创建期间将字段值设置为V§12.5


本规范未使用术语常量折叠

它的定义是

常量表达式是表示原语类型的值或字符串的表达式,该值或字符串不会突然完成,并且仅使用以下内容组成:

[……]

String类型的常量表达式始终处于内部,以便使用String.intern方法共享唯一实例

常量表达式始终被视为FP严格表达式,即使它发生在非常量表达式不被视为FP严格表达式的上下文中

常量表达式在switch语句中用作大小写标签,在赋值上下文和类或接口的初始化中具有特殊意义。它们还可以控制while、do或for语句正常完成的能力,以及条件运算符的类型:使用数字操作数

最后一部分已经指出了常量表达式的预计算是强制性的。当涉及到案例标签时,编译器需要报告重复项,因此,它必须在编译时计算值。在计算循环时,它必须计算常量布尔表达式以确定代码的可达性

同样,初始化者需要预先计算以确定正确性。例如:短s='a'*2;是正确的声明,但short s=short.MAX_值+1;事实并非如此

常量表达式的一个众所周知的用例是常量变量的初始值设定项。当读取常量变量时,将使用常量值代替读取变量,并与Q&a进行比较

但这并不意味着“不断折叠”是强制性的。理论上,一致性实现仍然可以在使用变量的每个位置执行变量初始值设定项中写入的常量表达式的计算。实际上,字节码格式会导致不断的折叠行为。用于记录字节码中常量变量值的属性只能保存预先计算的值。当针对已编译的类文件进行编译时,编译器无法使用常量变量的原始表达式。它只能使用预先计算的值

同样,通常使用 或指令,两者都要求为案例标签预先计算int值。编译器必须花很长的时间来实现不同的策略


此外,只能保存预先计算的表达式。

这允许对引用常量变量的名称进行常量折叠,但它不能解释所有常量折叠的情况,例如在编译时将2*3替换为6。@kaya3你说得对,我只想到常量字段。现在我明白了为什么JLS没有它,你知道其他Java官方文档是否有更多关于不断折叠的信息吗?