递归初始化:当我访问“类”字段时未调用静态初始化器 [英] Recursive initialization : Static Initializer not getting called when i access Class field

查看:87
本文介绍了递归初始化:当我访问“类”字段时未调用静态初始化器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

了解有关加载类和调用静态初始化程序的信息

Understanding about loading a class and calling static initializer

静态初始化程序以什么顺序进行阻塞

所以,我只是试图确认一下-

So, I just tried to confirm it -

public class OOMErrorB extends OOMErrorA {
    public static int c = 10;

    static {
        System.out.println("Loading static B " + c);
        System.out.println(OOMErrorA.a);
    }

    public static void main(String[] args) {
        new OOMErrorB();
    }
}

父类为-

public class OOMErrorA {
    public static int a = 20;

    static {
        a = a+ OOMErrorB.c;
        System.out.println("OOMErrorB.c " + OOMErrorB.c);
        System.out.println("loading OOMErrorA.a " + a);
    }
}

现在B的主要方法的输出

Now Output of main method of B -

**

OOMErrorB.c 0
loading OOMErrorA.a 20
Loading static B 10
20

**

我可以理解,首先它正在加载类A,因为它是父类,并且将其称为静态初始值设定项,

I can understand that first it is loading class A because it's Super class and calling it's static initializers,

现在是因为我正在访问OOMErrorB.c在OOMErrorA的静态块中,它应该加载并调用OOMErrorB的静态初始化程序。
因此,OOMErrorB.c应该是10而不是0。

now since i am accessing OOMErrorB.c in static block of OOMErrorA , it should load and call static initializer of OOMErrorB. so, OOMErrorB.c should be 10 and not 0 .

我知道有关加载和初始化类的知识-

What i know about loading and initializing of a class -

1) Class and gets loaded and variables are initialized to default values like for int - 0, Object - null.
2) Class field are initialized to specified values.
3) Static block gets called .

在我的程序中,我可以看到类OOMErrorB已加载(步骤1),但是步骤2而第3步未执行。

here in my program , i can see that class OOMErrorB got loaded (step 1) , but step 2 and step 3 didn't execute.

而根据链接上可接受的答案,它应该调用OOMErrorB的静态初始化程序。

whereas according to accepted answer on link, it should call static initializer of OOMErrorB.

所以它应该以循环依赖关系结束?

so it should end up in a cyclic dependency ?

推荐答案

访问 OOMErrorB.c时 OOMErrorB 已被 加载,因为它已经处于加载过程中(当JVM最初将其加载时)以调用 main 方法)。一旦将类加载到JVM中,就不会再次加载它。因此,不会发生循环依赖关系:提取 OOMErrorB 的静态成员 c ,目前该成员尚未初始化。

When accessing OOMErrorB.c, OOMErrorB is not loaded because it is already in the process of being loaded (when the JVM initially loaded it in order to invoke the main method). Once a class is loaded in the JVM, it will not be loaded again. Therefore, no cyclic dependency occurs: OOMErrorB's static member c is fetched, which at this moment is still not initialized.

您可以检查来自Java语言规范的这一部分有关类初始化的信息:

You can check this section from the Java language specification about class initialization:


因为Java编程语言是多线程的,因此类或接口的初始化需要仔细的同步,因为其他一些线程可能试图同时初始化同一类或接口。 还有可能作为类或接口初始化的一部分递归请求类或接口的初始化;例如,类A中的变量初始值设定项可能会调用不相关的类B的方法,而后者又可能会调用类A的方法。Java虚拟机的实现负责通过使用同步来实现同步和递归初始化。

Because the Java programming language is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time. There is also the possibility that initialization of a class or interface may be requested recursively as part of the initialization of that class or interface; for example, a variable initializer in class A might invoke a method of an unrelated class B, which might in turn invoke a method of class A. The implementation of the Java Virtual Machine is responsible for taking care of synchronization and recursive initialization by using the following procedure.

JVM具有锁定类初始化的正确方法,因此可以防止递归初始化。

The JVM has its proper way of locking the initialization of classes so that recursive initialization is prevented.

这篇关于递归初始化:当我访问“类”字段时未调用静态初始化器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆