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);
}