编译时常量和变量

NIN*_*OOP 37 java performance final constants compile-time-constant

Java语言文档说:

如果将基本类型或字符串定义为常量并且在编译时已知该值,则编译器会将代码中的常量名称替换为其值.这称为编译时常量.

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

private final int x = 10;
Run Code Online (Sandbox Code Playgroud)

然后,编译器将x用文字替换代码中的每个匹配项10.


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

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

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


另一个问题是以下代码行:

private int y = 10; // here y is not final
Run Code Online (Sandbox Code Playgroud)

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


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

  1. final static 表示编译时常量
  2. 只是final意味着它是一个常量但在运行时被初始化
  3. 只是static意味着在运行时初始化
  4. 不是final变量,不会被视为常量.

我的理解是否正确?

msi*_*msi 54

编译时间常数必须是:

  • 宣布决赛
  • 原语或字符串
  • 在声明中初始化
  • 用常量表达式初始化

所以private final int x = getX();不是一成不变的.

第二个问题private int y = 10;不是常数(在这种情况下是非最终的),因此优化器不能确定该值将来不会改变.所以它不能像恒定值那样优化它.答案是:不,它的处理方式与编译时间常数不同.

  • 定义常量表达式的JLS:http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28 (3认同)
  • 还有一个例子可以解决疑问:final int a = 1; 是一个编译时常量但是最终的int a; A = 2; 不是 (2认同)
  • @KorayTugay 你只是在玩术语。在 Java 世界中,我们使用“final”来表示不会改变的事物。和“常量”(或“编译时常量”)表示常量。对于没有 Java 经验并且来自其他语言的人来说,这可能很难理解,但是……您必须承认,“最终”和“常量”是不同的。https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.12.4 "常量变量是原始类型或字符串类型的最终变量,其初始化为常量表达式(第 15.28 节)。” (2认同)

小智 6

JLS使得之间的区别如下final变量和常量:

final 变量

可以声明一个变量final。一个final变量只能赋值一次。如果final变量被赋值,则是编译时错误,除非它在赋值之前明确未赋值(§16 (Definite Assignment))。

一旦final变量被赋值,它总是包含相同的值。如果final变量持有对对象的引用,则对象的状态可能会因对对象的操作而改变,但变量将始终引用同一个对象。这也适用于数组,因为数组是对象;如果final变量持有对数组的引用,则数组的组成部分可能会因对数组的操作而改变,但变量将始终引用同一个数组。

一个空白的final是一个final变量,其声明中缺少一个初始化。

常数

常量变量final原始类型或类型的变量 String,其与一个常量表达式(初始化§15.28)。

从这个定义中,我们可以看出一个常数必须是:

  • 宣布 final
  • 原始类型或类型 String
  • 在其声明中初始化(不是空白final
  • 常量表达式初始化

编译时常量呢?

JLS不包含短语编译时间常数。然而,程序员经常交替使用术语编译时常量常量

如果final变量不符合上述被视为常数的标准,则在技术上应将其称为final变量。