JVM如何在Java中加载父类

JVM如何在Java中加载父类,java,inheritance,initialization,classloader,Java,Inheritance,Initialization,Classloader,代码: 输出: class A { static { System.out.println("loading A static 1"); } static { System.out.println("loading A static 2 B.c= "+B.c); } static { System.out.println("loading static 3"); } stati

代码:

输出:

class A {
    static {
        System.out.println("loading A static 1");
    }
    static {
        System.out.println("loading A static 2 B.c= "+B.c);        
    }
    static {
        System.out.println("loading static 3");
    }
    static int a=10; 
    A(){        
    }
}

class B extends A{
    static {
       System.out.println("loading B A.a= "+A.a);
    }
    static int c = 50;
}
public class Test {
    public static void main(String[] args) {
        new B();
    }
}
从这个输出,我们可以说父类在子类之后加载,而子类在父类之后初始化吗?
如果是这样,JVM如何加载类层次结构?

您可以通过使用
java-verbose测试执行它来检查这一点:

loading A static 1
loading A static 2 B.c= 0
loading static 3
loading B A.a= 10

因此,不,父类也将首先加载。

初始化类时将执行静态块。我们知道

在初始化类之前,必须初始化其直接超类

因此,在初始化B时,它的超类在初始化之前会自动初始化


有关详细信息,您可以查看Java语言规范以及初始化类的过程

类或接口类型T将在 首次出现以下任何一种情况:

  • T是一个类,并且创建了T的一个实例

  • T是一个类,调用由T声明的静态方法

  • 分配了一个由T声明的静态字段

  • 使用T声明的静态字段,该字段不是常量变量(§4.12.4)

  • T是一个顶级类(§7.6),执行嵌套在T(§8.1.3)中的assert语句(§14.10)

[……]

在C的初始化锁LC上同步。这包括 等待直到当前线程可以获取LC

[……]

如果C的类对象指示正在进行初始化 对于当前线程的C,则这必须是对 初始化。释放信用证并正常完成

[……]

接下来,如果C是一个类而不是一个接口,那么它的超类是SC 尚未初始化,然后递归执行整个过程 SC程序。如有必要,首先验证并准备SC。如果 由于引发异常,SC的初始化突然完成, 然后获取LC,将C的类对象标记为错误,通知所有 等待线程,释放LC,然后突然完成,抛出相同的 初始化SC时产生的异常

所以

要求初始化类
B
。因为
B
a
的子类,
a
需要初始化。初始化
A

new B();
表示需要初始化
B
,但
B
已在初始化过程中,因此现在将忽略它,而
A
初始化将继续由于
B
的初始化未完成,字段
c
尚未初始化为50,因此它打印
0


A
初始化完成<代码>B
初始化继续<代码>B初始化完成并发出隆隆声!完成了。

那么,如果未加载类B,为什么在输出的第二行中给出B.c=0,B.c=0是如何产生的呢?谢谢,从输出中可以看到,两个类都已加载<代码>B.c尚未初始化,因此它仍然是
0
。我认为输出非常清楚地显示了所有内容的顺序。哦,明白了:)谢谢,你能告诉我JVM是如何知道类层次结构的吗?我不确定你的意思,你能澄清一点吗?您在代码中指定
A
B
的超类,
Object
始终是所有事物的超类,因此我认为它定义得非常好。我要问的是,如果我们要创建B的对象,父类A将首先加载。那么JVM如何解决B的超类是A?一个相关的问题:。
new B();
static {
    System.out.println("loading A static 2 B.c= "+B.c);        
}