为什么在这个简单的情况下静态初始化块没有运行?

7
 class Z
{
    static final int x=10;
    static
    {
        System.out.println("SIB");
    }

}
public class Y
{
    public static void main(String[] args)
    {
        System.out.println(Z.x);
    }
}

输出:10 为什么静态初始化块在这种情况下没有加载?当调用静态变量x时,类z的所有静态成员必须至少加载一次,但静态初始化块没有加载。

4
静态代码块中的代码为什么不会被执行? - Laabidi Raissi
6个回答

1
当JVM加载一个类时,它会将该类的所有常量成员放入常量区域中,当需要使用它们时,只需通过类名直接调用,也就是说,不需要实例化Z类。因此,静态初始化块不会被执行。

1
编译时,Z.x的值变为10,因为。
static final int x=10; is constant

编译器会在内联后创建以下代码:
System.out.println(10); //which is not calling Z class at runtime

+1 这似乎是一个原因。移除 final 关键字会执行静态块。可能是编译器优化的一种方式。 - Apurv
@Apurv:这个问题的重复链接(https://dev59.com/umfWa4cB1Zd3GeqPdAo-)中已经很好地解释了这一切。 - NPE
移除 static 或 final 将调用静态初始化块。移除 static 意味着我们必须在运行时创建类 Z 的对象,它将被加载。移除 final 意味着值可以被更改且不是常量值。 - AmitG

1
在声明中带有静态修饰符的字段称为“静态字段”或“类变量”。它们与类相关联,而不是与任何对象相关联。类的每个实例共享一个类变量,该变量位于内存中的一个固定位置。任何对象都可以更改类变量的值,但也可以在不创建类的实例的情况下操作类变量。
因此,当您调用以下代码中的Z.x时:
System.out.println(Z.x);

除非您调用Z.x,否则它不会初始化该类,但它将从固定的内存位置获取x
当JVM加载class Z时,静态块运行。在这里,它可以直接访问x而无需加载该类,因此该类永远不会被加载。

0
如果一个常量被声明为static final,那么它被称为完美常量。当编译器编译类y并在编译sop(Z.x)时,它将sop(Z.x)替换为sop(10),因为x是一个完美常量,这意味着在字节码类Y中不使用类Z,因此在运行类Y时,类Z不会被加载,这就是为什么类Z的SIB没有被执行的原因。

0
如果X不是final的话,那么JVM就必须加载类'Z',然后才能执行静态块。现在JVM不需要加载'Z'类,因此静态块不会被执行。

0

它无法运行,因为该类从未被加载。

public class Y
{
    public static void main(String[] args)
    {
        Z z new Z(); //will load class
        System.out.println(Z.x);
    }
}

由于在Z上声明了带有static finalx字段,它们被创建在固定的内存位置。访问此字段不需要加载类。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接