为什么引用静态final字段不会触发类加载?

2024-03-27

我有一个这样的测试代码:

public class Constants {
public static String c1 = "C1";

static {
    System.out.println("Constants Class Loaded!");
}
}

public class Test {
    public static void main(String[] args) {
        String c1 = Constants.c1;
        System.out.println(c1);
    }
}

其输出为:

Constants Class Loaded!
C1

因此,Constants 类是由 JVM 加载的。 但是如果我在类 Constants 的静态字段中添加一个final关键字:

public class Constants {
public static final String c1 = "C1";

static {
    System.out.println("Constants Class Loaded!");
}
}

其输出更改为:

C1

看来 Constants 类没有加载。

我本地的环境是:

OS: Win7 x64
JVM: JRockit (build R28.2.0-79-146777-1.6.0_29-20111005-1808-windows-ia32, compiled mode)

所以,我的问题是:

  • 为什么引用静态final字段不会触发类加载?当JVM遇到这段代码时会做什么(字节码)?
  • 这个行为取决于特定的 JVM 吗?或者这是Java语言规范中的规则?
  • 这样做的优点和缺点是什么?

Thanks.


为什么引用静态final字段不会触发类加载? 当JVM遇到这段代码时会做什么(字节码)?

JLS 说 http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4

类或接口类型 T 将在紧接之前初始化 第一次出现以下任一情况:

  • [...]
  • 使用 T 声明的静态字段,并且该字段不是常量变量(第 4.12.4 节)。

A 常数变量 http://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.12.4定义为

常量变量是final原始类型或类型的变量String它是用常量表达式初始化的(第 15.28 节)。

所以你的字段是一个常量变量,访问它不会导致类型被初始化。

这个行为取决于特定的 JVM 吗?或者这是Java中的规则 语言规范?

Java 语言规范指定了此行为。

这样做的优点和缺点是什么?

缺点是它可能会引起混乱(如果您不了解 Java 语言规范的详细信息)。

优点是引用常量不会导致任何不必要的代码执行。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么引用静态final字段不会触发类加载? 的相关文章

随机推荐