Java-这段代码中的初始化顺序是什么?

Java-这段代码中的初始化顺序是什么?,java,oop,Java,Oop,在下面的Java代码中,昆虫类由甲壳虫类继承 class Insect { private int i = 9; protected int j; Insect() { System.out.println("i = " + i + ", j = " + j); j = 39; } private static int x1 = printInit("static Insect.x1 initia

在下面的Java代码中,昆虫类由甲壳虫类继承

class Insect {

    private int i = 9;
    protected int j;

    Insect() {
        System.out.println("i = " + i + ", j = " + j);
        j = 39;
    }
    private static int x1
            = printInit("static Insect.x1 initialized");

    static int printInit(String s) {

        System.out.println(s);
        return 47;
    }
}

public class Beetle extends Insect {

    private int k = printInit("Beetle.k initialized");

    public Beetle() {
        System.out.println("k = " + k);
        System.out.println("j = " + j);
    }
    private static int x2
            = printInit("static Beetle.x2 initialized");

    public static void main(String[] args) {
        System.out.println("Beetle constructor");
        Beetle b = new Beetle();
    }
}
输出在某种程度上是一致的

已初始化static.x1

静态甲壳虫.x2已初始化

甲虫构造器

i=9,j=0

甲虫

k=47 j=39

此特定示例中的初始化顺序是什么?

为什么x2在x1之后立即初始化?为什么主方法(
System.out.println(“甲壳虫构造函数”);
)的第一行在x1和x2初始化之后执行。太令人困惑了


我知道派生类构造函数会自动调用基类构造函数(除非它有参数并且您会使用super关键字)。我知道变量在构造函数之前初始化,静态变量在其他变量之前初始化。

x1
x2
是静态的。这意味着它们在类加载时被初始化。由于main方法位于
bellet
中,因此必须在调用
main
之前加载该类。这就是为什么您首先看到的是
x1
x2
初始化。我不知道为什么这两个人的顺序是这样的

现在您正在调用
main
System.out.println(“甲虫构造函数”)被执行。然后它调用
甲虫()
,甲虫()首先隐式调用
超级()
(又称
昆虫()
)。这将打印
i=9,j=0
,因为
i
是9,并且
j
在该点尚未初始化,这意味着它具有默认的int值0


现在
j
被设置为39,并且在
甲壳虫()
中继续流动。现在,在您的例子中,
k
初始化了
甲壳虫
的字段。因此,对于
甲壳虫()
中的显式代码,
k
由超级构造函数初始化为47,
j
初始化为39。

x1
x2
是静态的。这意味着它们在类加载时被初始化。由于main方法位于
bellet
中,因此必须在调用
main
之前加载该类。这就是为什么您首先看到的是
x1
x2
初始化。我不知道为什么这两个人的顺序是这样的

现在您正在调用
main
System.out.println(“甲虫构造函数”)被执行。然后它调用
甲虫()
,甲虫()首先隐式调用
超级()
(又称
昆虫()
)。这将打印
i=9,j=0
,因为
i
是9,并且
j
在该点尚未初始化,这意味着它具有默认的int值0


现在
j
被设置为39,并且在
甲壳虫()
中继续流动。现在,在您的例子中,
k
初始化了
甲壳虫
的字段。因此,对于
bellet()
中的显式代码,
k
由超级构造函数初始化为47,
j
初始化为39-

由于静态成员是非实例成员,即在类的所有实例中只共享成员的一个副本,因此首先初始化这些成员

在这种情况下,x1首先被初始化,因为它是存在main方法的类的基类中的静态成员

因此,1st x1被初始化

子类中的静态成员x2之所以出现,是因为同样的原因,也因为昆虫类中没有其他静态成员

甲虫构造器行是从主方法打印出来的


超类和子类的构造函数一个接一个地被调用,原因很明显

这可以解释如下-

由于静态成员是非实例成员,即在类的所有实例中只共享成员的一个副本,因此首先初始化这些成员

在这种情况下,x1首先被初始化,因为它是存在main方法的类的基类中的静态成员

因此,1st x1被初始化

子类中的静态成员x2之所以出现,是因为同样的原因,也因为昆虫类中没有其他静态成员

甲虫构造器行是从主方法打印出来的

超级类和子类的构造函数被一个接一个地调用,原因很明显

JVM(类加载器)在调用甲虫类的主要静态方法时加载甲虫类。类加载后,将初始化甲壳虫类,这意味着初始化该类的所有静态成员

基类总是隐式初始化的,因此可以看到x1在x2之前初始化

您会看到在x1和x2之后打印的“甲壳虫构造函数”,因为当您引用一个类的静态方法(正如您调用main所做的那样)时,JVM的执行顺序会跳到初始化类的静态成员,然后再继续执行main()方法

作为一个实验,尝试将主方法移到另一个类中

public class Beetle1 {
 public static void main(String[] args) {
        System.out.println("Beetle1 constructor");
    }
}
现在由于甲虫构造函数没有被引用,类加载器不会加载它,您将看到打印的甲虫1构造函数。

JVM(类加载器)在调用甲虫类的主要静态方法时加载甲虫类。类加载后,将初始化甲壳虫类,这意味着初始化该类的所有静态成员

基类总是隐式初始化的,因此可以看到x1在x2之前初始化

您会看到在x1和x2之后打印的“甲壳虫构造函数”,因为当您引用一个类的静态方法(正如您通过调用main所做的那样)时,JVM的执行顺序会跳到初始化cla