java - 静态最终变量以及静态初始化程序 block

标签 java

我创建了一个包含以下内容的类:

  1. static final 变量
  2. static 带有 System.out.println() 语句的初始化程序 block

如果我从另一个类调用 static final 变量,static block 不会执行。

据我所知,static 初始化程序 block 在类加载到内存中时执行。

在这种情况下,内存级别发生了什么?

类没有加载到内存中吗?如果不是,其他类从哪里获取final static变量的地址?


情况 1: static block 不执行

class Test2 {
    static final int a = 20;

    static {
        System.out.println("one");
    }
}

情况 2:static block 执行

class Test2 {
    static final int a;

    static {
        a = 20;
        System.out.println("one");
    }
}

输出

class Test {
    public static void main(String[] args) {
        System.out.println(Test2.a);
    }
}
  • 案例一:

    20
    
  • 案例 2:

    one
    20
    

那么在这两个层面上发生了什么?

最佳答案

我的猜测是您的字段是原始类型或 String,并且使用编译时常量表达式进行了初始化。

对于用常量表达式初始化的静态最终字段(并且只有这样的字段)——任何引用该字段的代码都会将常量值嵌入其中,而不是通过会导致类初始化的静态字段。 “常量表达式”部分很重要。我们可以通过一个小型测试应用程序看到这一点:

class Fields {
    
    public static final String CONSTANT = "Constant";
    public static final String NON_CONSTANT = new String("Non-constant");
    
    static {
        System.out.println("Initializing");
    }
}

public class Test {
    public static void main(String arg[]) {
        System.out.println(Fields.CONSTANT);
        System.out.println(Fields.NON_CONSTANT);
    }
}

输出是:

Constant
Initializing
Non-constant

访问常量字段不需要初始化,但访问非常量字段需要。使用非 final 字段会产生相同的效果:基本上,它不再算作常量。

有关“这是一个常量”的信息被嵌入到声明字段的类中。例如,使用 javap -c Fields 我们可以看到两个字段:

public static final java.lang.String CONSTANT;
  flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL
  ConstantValue: String Constant

public static final java.lang.String NON_CONSTANT;
  flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL

请注意 CONSTANT 字段元数据的 ConstantValue 部分,它在 NON_CONSTANT 字段元数据中缺失。

参见 section 15.28 of the JLS有关什么构成常量表达式的更多信息。

Section 12.4.1 of the JLS指定类何时初始化:

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.

  • T is a class and a static method declared by T is invoked.

  • A static field declared by T is assigned.

  • A static field declared by T is used and the field is not a constant variable (§4.12.4).

  • T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.

(强调我的。)

关于java - 静态最终变量以及静态初始化程序 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18997197/

相关文章:

java - 使用 guice,如何配置 Jersey 的媒体类型映射?

java - Vaadin 14 网格 + 对话框 : How to refresh grid after closing dialog?

java - 继承同名但返回类型不同的方法

java - GridLayout Jpanel 添加不考虑首选大小

java - Java Applet 中的网络摄像头

java - 合并第三个数组中的两个数组同时按升序对第三个数组进行排序

java - 我已经为 RSA 加密和解密编写了一个 Java 代码,其中解密 key 太大,因此解密过程需要永远执行

java - Z3 Java : simplify a distributive expression

java - Google App Engine - 生成二维码

java - 如何处理 Java Web 应用程序中的异常?