未执行 Java 中的静态块

2022-08-31 11:31:47
class Test {
    public static void main(String arg[]) {    
        System.out.println("**MAIN METHOD");
        System.out.println(Mno.VAL); // SOP(9090);
        System.out.println(Mno.VAL + 100); // SOP(9190);
    }

}

class Mno {
    final static int VAL = 9090;
    static {
        System.out.println("**STATIC BLOCK OF Mno\t: " + VAL);
    }
}

我知道在类加载时执行了一个块。但是在这种情况下,类内的实例变量是 ,因为块没有执行。staticMnofinalstatic

为什么会这样?如果我删除 ,它会正常工作吗?final

将首先分配哪个内存,变量还是块?static finalstatic

如果由于访问修饰符导致类未加载,那么变量如何获取内存?final


答案 1
  1. 字段是编译时常量,其值被硬编码到目标类中,而不引用其原点;static final int
  2. 因此,您的主类不会触发包含该字段的类的加载;
  3. 因此,不会执行该类中的静态初始值设定项。

具体来说,编译后的字节码对应于这个:

public static void main(String arg[]){    
    System.out.println("**MAIN METHOD");
    System.out.println(9090)
    System.out.println(9190)
}

一旦删除 ,它就不再是编译时常量,并且上述特殊行为不适用。该类按预期方式加载,并执行其静态初始值设定项。finalMno


答案 2

未加载该类的原因是 AND 它使用常量表达式 (9090) 进行初始化。当且仅当满足这两个条件时,将在编译时计算常量,并在需要时“硬编码”。VALfinal

要防止在编译时计算表达式(并使 JVM 装入您的类),您可以:

  • 删除最终关键字:

    static int VAL = 9090; //not a constant variable any more
    
  • 或者将右侧表达式更改为非常量(即使变量仍然是最终的):

    final static int VAL = getInt(); //not a constant expression any more
    static int getInt() { return 9090; }
    

推荐