初始化块和构造器的比较、总结

时间:2021-09-15 17:22:21

初始化块分为:静态初始化块和普通初始化块。

在定义初始化块时使用了static修饰符,静态初始化块(也叫做类初始化块);否则,就是普通初始化块。

与静态方法、非静态方法的理解其实类似,普通初始化块负责对对象执行初始化,类初始化块负责对类执行初始化。

为了更好地区分,上一段代码:

package object_down;

class Root{
	static {
		System.out.println("Root的静态初始化块");
	}
	{
		System.out.println("Root的普通初始化块");
	}
	public Root(){
		System.out.println("Root的无参数的构造器");
	}
}
class Mid extends Root{
	static {
		System.out.println("Mid的静态初始化块");
	}
	{
		System.out.println("Mid的普通初始化块");
	}
	public Mid() {
		System.out.println("Mid的无参数的构造器");
	}
	public Mid(String msg) {
		this(); //this()函数会在末尾进行解释,如果此处不太理解this()函数的意思的话,请跳转末尾
		System.out.println("Mid的带参数构造器,其参数值为:"+msg);
	}
}
class Leaf extends Mid{
	static {
		System.out.println("Leaf的静态初始化块");
	}
	{
		System.out.println("Leaf的普通初始化块");
	}
	public Leaf() {
		super("大学物理");
		System.out.println("执行Leaf的构造器");
	}
}
public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Leaf();
		new Leaf();
	}

}

运行结果见下:

Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值为:大学物理
Leaf的普通初始化块
执行Leaf的构造器
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值为:大学物理
Leaf的普通初始化块
执行Leaf的构造器

为啥生成两个Leaf()对象,却要执行那么多的函数呢?

答案见下:

第一次创建一个Leaf()对象时,因为系统中还不存在Leaf()类,因此需要先加载并初始化Leaf类。

而初始化Leaf类其实也是一个蛮麻烦的过程:初始化Leaf类需要先执行其顶层父类的静态初始化块(因为是对类初始化的嘛!),再执行其直接父类的静态初始化块,最后才执行Leaf本身的静态初始化块。

一旦Leaf类初始化成功后,Leaf类在JVM中将一直存在,因此当第二次创建Leaf实例时,无需再次对Leaf类进行初始化。

每次创建一个Leaf对象时,都需要先执行最顶层的父类的初始化块,构造器,然后再执行其父类的初始化块、构造器……最后才执行Leaf的初始化块,构造器。(注意:创建对象时执行的初始化块是普通初始化块,它负责对对象执行初始化)

初始化块和构造器的比较、总结

最后,上面代码中有一段中有一个this()函数,在此作以下解释:

package test_test;

import java.util.*;

public class Test {
    private int x;
    private int y;
    private int z;
   
    public Test(int x, int y) {
        this.x = x;
        this.y = y;
        System.out.println("Test的含有两个参数的构造器");
    }

    public Test(int x, int y, int z) {
        this(x,y);
        this.z = z;
        System.out.println("Test的含有三个参数的构造器");
    }
    
    public static void main(String []args) {
    	new Test(100,10);
    	System.out.println("-------------------------");
    	new Test (1, 2,3);
    }

}

输出结果:

Test的含有两个参数的构造器
-------------------------
Test的含有两个参数的构造器
Test的含有三个参数的构造器
this()方法只能用在构造函数中,同时为了避免操作对象时对象还未构建成功,需要this()和super()的调用在第一行实现【以此来创建对象】,防止异常。