编译时常量和变量

Java语言文档说:


如果将原始类型或字符串定义为常量,并且在编译时知道该值,则编译器会使用其值替换代码中各处的常量名称。这称为编译时常量。


我的理解是,如果我们有一段代码:


private final int x = 10;

然后,编译器会将x代码中每次出现的内容替换为literal 10。


但假设常量在运行时初始化:


private final int x = getX(); // here getX() returns an integer value at run-time.

与编译时常数相比,性能是否会下降(无论可以忽略不计)?


另一个问题是下面的代码行:


private int y = 10; // here y is not final

被编译器以与编译时常量相同的方式处理?


最后,我从答案中了解到的是:


final static 表示编译时常数

只是final意味着它是一个常量,但是在运行时初始化

只是static意味着在运行时初始化

没有final是变量,不会被视为常量。

我的理解正确吗?


白板的微信
浏览 714回答 3
3回答

交互式爱情

编译时间常数必须为:宣布最终原始或字符串在声明中初始化用常量表达式初始化所以private final int x = getX();不是恒定的。第二个问题private int y = 10;不是恒定的(在这种情况下是非最终的),因此优化器无法确定该值将来不会更改。因此,它无法将其优化为恒定值。答案是:不,它与编译时间常数的处理方式不同。

犯罪嫌疑人X

该JLS使得之间的区别如下final变量和常量:final 变数可以声明一个变量final。甲final变量可以仅被分配给一次。如果将final变量赋值给它,则是编译时错误,除非在赋值之前绝对未赋值(第16节(确定赋值))。一旦一个final变量被分配,它总是包含相同的值。如果final变量持有对对象的引用,则可以通过对对象的操作来更改对象的状态,但是变量将始终引用同一对象。这也适用于数组,因为数组是对象。如果final变量持有对数组的引用,则可以通过对数组的操作来更改数组的组件,但是变量将始终引用同一数组。一个空白的final是一个final变量,其声明中缺少一个初始化。常数甲常量变量是final原始类型或类型的变量 String,其与一个常量表达式(初始化§15.28)。从这个定义中,我们可以看出一个常数必须是:宣告 final原始类型或类型 String在其声明中初始化(不是空白final)用常量表达式初始化编译时常量呢?该JLS不包含短语编译时间常数。但是,程序员经常将术语“ 编译时常量”和“ 常量常量”互换使用。如果final变量不满足上述标准,则该final变量在技术上应称为变量。

哆啦的时光机

根据JLS,没有要求“常量”应该是静态的。因此,“常量”可以是静态的也可以是非静态的(实例变量)。但是JLS对变量成为“常量变量”(除了只是最终变量)施加了一些其他要求:仅是字符串或原始仅初始化为内联,因为它是最终的,并且不允许空白的最终用“常量表达式” =“编译时常量表达式”初始化(请参见下面的JLS引用)4.12.4。最终变量(JLS)甲常量变量是原语类型的最终变量或输入与一个常量表达式初始化字符串(§15.28) 。15.28。常数表达式甲编译时间常量表达式是表示原始类型或String不突然完成,并且仅使用以下组成的一个值的表达式:基本类型的文字和字符串类型的文字(§3.10.1,§3.10.2,§3.10.3,§3.10.4,§3.10.5)强制转换为基本类型,强制转换为字符串(第15.16节)一元运算符+,-,〜和!(但不是++或-)(§15.15.3,§15.15.4,§15.15.5,§15.15.6)乘法运算符*,/和%(第15.17节)加法运算符+和-(§15.18)移位运算符<<,>>和>>>(第15.19节)关系运算符<,<=,>和> =(但不包括instanceof)(第15.20节)等号运算符==和!=(§15.21)按位和逻辑运算符&,^和| (§15.22)条件和运算符&&和条件或运算符|| (§15.23,§15.24)三元条件运算符?:(§15.25)带括号的表达式(第15.8.5节),其包含的表达式是一个常量表达式。引用常量变量(第4.2.4节)的简单名称(第6.6.5.6.1节)。TypeName形式的合格名称(第6.5.6.2节)。引用常量变量的标识符(第4.12.4节)。
打开App,查看更多内容
随时随地看视频慕课网APP