3

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类还没有加载。但是,当我输入 as 时2只有 Example 类被加载到 JVM 中,如详细输出所示,然后执行 Example 内的静态块,并且j初始化然后打印的值。

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

4

1 回答 1

2

根据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)。

于 2020-08-22T10:31:58.193 回答