【Java学习笔记】类初始化执行顺序

时间:2023-02-26 18:41:21

在网上看到许多人推荐《Java编程思想》这本书,于是拿来入门Java了。
结果越看越火大,一路上都在乱黑C++,举出来的所谓Java优势也是越看越废物。搁C++那儿,哪来这么多破事。这就算了,作者还把Java的基本知识弄错了,我不动手实验的话还不知道。还好我没买实体书,要不然早一把火烧了。

首先关于类是否被JVM装载的问题:
1、当类的静态成员或静态函数被访问时,类与它的基类会被装载;
2、在类被第一次实例化之前,类与它的基类会被装载。
除此以外的行为,不会引起类的装载。

当类被装载时,静态部分的初始化顺序是:
1、为所有静态成员与静态方法分配内存,并将静态成员置零或置null;
2、如果存在基类,并且基类未被装载,则对基类执行此步骤;
3、按照书写顺序,为静态成员赋初值;
4、执行静态代码块。

然后是实例化时的初始化过程:
1、为类的所有成员分配内存,并将值置零或置null;
2、如果存在基类,则回到第一步并执行基类的初始化;
3、按照书写顺序,为类的非静态成员赋初值;
4、执行非静态代码块;
5、执行构造函数。

注意,基类的静态方法不会被覆盖,而非静态方法会被覆盖。

以下是实验代码:

class InitTestBase{
static String name = getName();
static String getName() { return "InitTestBase"; }
static {
System.out.println("InitTestBase loaded.");
System.out.println("Static InitTestBase.name = " + name);
}
protected String state = "Base Initialized";
{
Overrided("InitTestBase");
}
void Overrided(String parent){
System.out.println("InitTestBase.state = \""+state+"\""
+ ", invoked by " + parent);
}
InitTestBase(){
System.out.println("InitTestBase() invoked.");
}
}

class InitTest extends InitTestBase{
static String name = getName();
static String getName() { return "InitTest"; }
static {
System.out.println("InitTest loaded.");
System.out.println("Static InitTest.name = " + name);
}
void Overrided(String parent){
System.out.println("InitTest.state = \""+state+"\""
+ ", invoked by " + parent);
}
protected String state = "Initialized";
{
Overrided("InitTest");
}
InitTest(){
System.out.println("InitTest() invoked.");
}
}

public class Main{
static{
System.out.println("Main loaded.");
}
public static void main(String[] args) {
System.out.println("main() invoked.");
new InitTest();
}
}

它的运行结果为:

Main loaded.
main() invoked.
InitTestBase loaded.
Static InitTestBase.name = InitTestBase
InitTest loaded.
Static InitTest.name = InitTest
InitTest.state = "null", invoked by InitTestBase
InitTestBase() invoked.
InitTest.state = "Initialized", invoked by InitTest
InitTest() invoked.