普通初始化块(负责对象执行初始化)
- 没有任何修饰词,没有任何名字,只有一对 {} ,多个普通块会按普通块的顺序先后执行,而且优先于构造方法(器)执行。
- 定义多个普通初始化块其实没有意义,所有块最终都是要执行的,所以尽可能的合并一个即可,可读性更好。
- 当一个类加载后,系统为对象实例变量分配内存的时候。顺序:先执行初始块 或者 声明实例变量初始值(两者优先级相同,看谁在前面先执行谁)
- 如果一个构造器中,有一些无需参数的初始化行为(无参方法…),就可以把他们放在初始化块中去
- 实际上,使用javac编译java类后,初始化代码会进入每一个构造器中,并且位于构造器所有代码的前面。所以当创建一个对象的时候,系统会一直往上查找直到object类,然后再从object类的初始化块、构造器依次往下执行,最后才到该类的初始化块和构造器。
静态初始化块(负责类执行初始化)
- 优先于普通初始化块执行
当在主类中new两个子类的子类对象,代码的执行顺序:
1,首先从object的静态初始化块开始依次加载,因为要先加载类,一旦加载类就会加载静态初始化块。
2,加载完类后,依次从object类往下加载普通代码块和构造器(无参+有参)
3,加载完第一个对象以后,记载第二个对象的时候不再会调用static代码块,static代码块只在加载类的时候加载,所以从加载普通代码块开始了。
class Root
{
static{
System.out.println("father的静态初始化块");
}
{
System.out.println("father的普通初始化块");
}
public Root()
{
System.out.println("father的无参数的构造器");
}
/*public Root(String msg) {
System.out.println("Root的带参数构造器,其参数值:"
+ msg);
}*/
}
class Mid extends Root
{
static{
System.out.println("son的静态初始化块");
}
{
System.out.println("son的普通初始化块");
}
public Mid()
{
System.out.println("son的无参数的构造器");
}
public Mid(String msg)
{
// 通过this调用同一类中重载的构造器
this();
System.out.println("son的带参数构造器,其参数值:"
+ msg);
}
}
class Leaf extends Mid
{
static{
System.out.println("son_son的静态初始化块");
System.out.println("============================");
}
{
System.out.println("son_son的普通初始化块");
System.out.println("============================");
}
public Leaf()
{
// 通过super调用父类中有一个字符串参数的构造器
super("疯狂Java讲义");
System.out.println("执行son_son的构造器");
}
}
public class Demo06_instanceof
{
public static void main(String[] args)
{
new Leaf();
//System.out.println("============================");
new Leaf();
}
}
执行结果:
father的静态初始化块
son的静态初始化块
son_son的静态初始化块
============================
father的普通初始化块
father的无参数的构造器
son的普通初始化块
son的无参数的构造器
son的带参数构造器,其参数值:疯狂Java讲义
son_son的普通初始化块
============================
执行son_son的构造器
father的普通初始化块
father的无参数的构造器
son的普通初始化块
son的无参数的构造器
son的带参数构造器,其参数值:疯狂Java讲义
son_son的普通初始化块
============================
执行son_son的构造器