首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java语言规范,Java 11版(JLS SE 11)中常量折叠的描述在哪里?

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

Stack Overflow用户
提问于 2020-08-10 23:35:00
回答 3查看 255关注 0票数 0

据我所知,Java在编译时通过常量折叠处理常量变量第4.12.4节。我已经尽力了,但是我找不到JLS的描述。有人能告诉我在哪里可以找到官方描述的常量折叠过程的Java11吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-08-11 09:01:29

规范中没有使用常量折叠这个术语。

它有常量表达式的定义

常量表达式是一个表达式,它表示一个原始类型的值或一个String,该表达式不会突然完成,并且仅使用以下方法组成: … String类型的常量表达式总是“内部”的,以便使用String.intern方法共享唯一的实例。 一个常数表达式总是被视为FP严格(第15.4节),即使它发生在一个非常数表达式不会被认为是FP严格的上下文中。 常量表达式在case语句(https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-14.11)中用作switch标签,在赋值上下文(https://docs.oracle.com/javase/specs/jls/se11/html/jls-5.html#jls-5.2)和类或接口(https://docs.oracle.com/javase/specs/jls/se11/html/jls-12.html#jls-12.4.2)的初始化中具有特殊意义。它们还可以控制while__、do__或for语句正常完成(https://docs.oracle.com/javase/specs/jls/se11/html/jls-14.html#jls-14.21)的能力,以及带有数字操作数的条件运算符? :的类型。

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

同样,初始化程序需要预先计算以确定正确性。例如,short s = 'a' * 2;是一个正确的声明,但short s = Short.MAX_VALUE + 1;不是。

常量表达式的一个众所周知的用例是常量变量的初始化器。当读取常量变量时,将使用常量值代替读取变量,并与Q&A “JLS是否需要最终字符串常量的内联?”进行比较。

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

同样,说明通常使用tableswitchlookupswitch指令来完成,两者都需要为case标签预先计算int值。编译器需要花费很长的时间才能实现不同的策略。

此外,注释值的编译格式。只能保存预先计算的表达式。

票数 3
EN

Stack Overflow用户

发布于 2020-08-11 00:00:56

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

也就是说,JLS确实定义了语言语义,允许在更多情况下进行常量折叠,而不改变程序的行为。最相关的段落可能是你在§14.2.4中提到的

常量变量是由常量表达式初始化的原始类型或类型字符串的最终变量(§15.28)。变量是否为常量变量可能涉及类初始化(§12.4.1)、二进制兼容性(§13.1)、可达性(§14.21)和确定赋值(§16.1.1)。

所引用的有关类初始化、二进制兼容性、可达性和确定赋值的部分专门定义了常量变量的语义,与其他变量不同;具体来说,它们定义的行为是您期望编译器提供的行为,它可以折叠常量。这允许那些实现规范的人在不过分限制他们如何进行优化的情况下进行优化。

票数 2
EN

Stack Overflow用户

发布于 2020-08-11 00:11:39

字段的过程是从问题:https://docs.oracle.com/javase/specs/jls/se11/html/jls-13.html#jls-13.1链接的页面链接的。

对常量变量(§4.12.4)的字段的引用必须在编译时解析为由常量变量的初始化器表示的值V。 如果这样的字段是静态的,那么二进制文件中的代码中不应该存在对该字段的引用,包括声明该字段的类或接口。这样的字段必须始终看起来已经初始化(§12.4.2);字段的缺省初始值(如果与V不同)绝不能被观察到。 如果这样的字段是非静态的,那么除了包含字段的类之外,二进制文件中的代码中不应该存在对字段的引用。(它将是一个类,而不是一个接口,因为接口只有静态字段。)类应该有代码,以便在实例创建期间将字段的值设置为V (§12.5)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63349469

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档