乐趣区

java小心机(5)| 浅谈类成员初始化顺序

类成员什么时候会被初始化呢? 一般来说:” 类的代码在初次使用时才被加载 ”, 加载过程包括了初始化。
比如说 new A()调用构造函数时, 类中全部成员都会被初始化。
但对于 static 域 (包括静态成员变量、静态代码块、静态方法), 当某个 static 域被调用时, 类中的的所有 staict 就会被初始化, 按照定义顺序(即书写顺序) 初始化, 且只会初始化一次(N 个实例共用)`。`
static 域的初始化优先级要优于普通成员(即非静态域)
下文代码例子名称解释: 静态域: 静态代码块、静态成员变量非静态域:非静态代码块、非静态成员变量(ps: 成员方法不包含在里面, 因为方法只能讲加载而非初始化)
在没有继承父类的情况下:
class HelloA {
public HelloC helloC1 = new HelloC(“ 普通成员 C1 构造函数前 ”);

public HelloA() {
System.out.println(“ 构造函数 A ”);
}

public HelloC helloC2 = new HelloC(“ 普通成员 C2 构造函数后 ”);

static {
System.out.println(“ 静态块 A ”);
}

public HelloC helloC3 = new HelloC(“ 普通成员 C3 静态块后 ”);

{
System.out.println(“ 非静态块 A ”);
}

public HelloC helloC4 = new HelloC(“ 普通成员 C4 非静态块后 ”);

public static HelloC helloC5 = new HelloC(“ 静态成员 C5”);

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

class HelloC {
public HelloC(String str) {
System.out.println(str);
}
}

//out:
静态块 A
静态成员 C5
普通成员 C1 构造函数前
普通成员 C2 构造函数后
普通成员 C3 静态块后
非静态块 A
普通成员 C4 非静态块后 构造函数 C
构造函数 A
可以看出, 初始化顺序为: 静态域 -> 非静态域 -> 构造函数以上面优先级并按所定义的顺序初始化(即书写顺序)
在有继承父类的情况下:
class HelloA extends HelloB{

public HelloA() {
System.out.println(“ 子类: 构造函数 A ”);
}

static {
System.out.println(“ 子类: 静态块 A ”);
}

{
System.out.println(“ 子类: 非静态块 A ”);
}

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

class HelloB {
public HelloB() {
System.out.println(“ 父类: 构造函数 B ”);
}

static {
System.out.println(“ 父类: 静态块 B ”);
}

{
System.out.println(“ 父类: 非静态块 B ”);
}
}

//out:
父类: 静态块 B
子类: 静态块 A
父类: 非静态块 B
父类: 构造函数 B
子类: 非静态块 A
子类: 构造函数 A
从结果可以看出, 初始化顺序为: 父类静态域 -> 子类静态域 -> 父类非静态域 -> 父类构造函数 -> 子类非静态域 -> 子类构造函数
这里说明一点:这是初始化顺序,不等同于语句程序的执行过程。因此在上面的初始化顺序里没有成员方法(静态或者非静态都没有),这是因为成员方法都是调用了才执行,虽然静态方法已经被加载进了方法区,但初始化过程中并没有执行过。
推荐阅读:
「趣图」HTTP 状态码共享单车, 要凉凉了?
点击阅读原文, 阅读「java 小心机」系列文章
您的点赞、转发是对我最大的支持!

 THANDKS
End –
一个立志成大腿而每天努力奋斗的年轻人
伴学习伴成长,成长之路你并不孤单!

退出移动版