类加载与初始化:Java静态最终变量



Example.java

public class Example {
static final int i = 10;
static int j = 20;
static {
System.out.println("Example class loaded and initialized");
}
}

使用.java

import java.util.Scanner;
public class Use {
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int ch = 1;
while(ch != 0) {
System.out.print("Enter choice: ");
ch = sc.nextInt();
if (ch == 1) {
System.out.println("Example's i = " + Example.i);
} else if(ch == 2){
System.out.println("Example's j = " + Example.j);
}
}
}
}

当我使用java -verbose:class Use运行,并将输入作为1时,则输出为10,即恒定的i值。但Example类尚未加载。然而,当我将输入作为2时,只有Example类被加载到JVM中,如详细输出所示,然后执行Example中的静态块,初始化并打印j的值。

我的查询是:如果对于输入1,即当在另一个类Use中请求类Example的静态最终(常量(值时,那么如果在此之前从未将类Example加载到JVM中,则从哪里获取常量值?静态最终i是何时以及如何初始化并存储到JVM内存中的?

根据Java语言规范第12.4.1节(增加强调(:

类或接口类型T将在首次出现以下任一情况:

  • T是一个类,并创建了T的实例。

  • 调用由T声明的静态方法。

  • 指定了一个由T声明的静态字段。

  • 使用由T声明的静态字段,并且该字段不是常量变量(§4.12.4(

常量变量是用常量表达式初始化的最终变量。在您的代码中,Example.i是一个常量变量,因此不会导致类被加载。

那么,如果没有加载类,那么com的值从哪里来?

语言规范要求编译器内联其值。来自二进制兼容性13.1部分:

  1. 对常量变量字段(§4.12.4(的引用必须是在编译时解析为由常数表示的值V变量的初始值设定项。

    如果这样的字段是静态的,则不应引用该字段存在于二进制文件中的代码中,包括类或接口它声明了字段。这样一个领域似乎总是已初始化(§12.4.2(;字段的默认初始值(如果不同于V(。

最新更新