类的初始化顺序详解

前言

先声明一个常识,类域和局部变量初始化的差异如下,
局部变量不初始化会报错:
类的初始化顺序详解_第1张图片

类中属性(也称域)不赋初值,默认为0,如果是引用默认为空。
类的初始化顺序详解_第2张图片


正题

一、类中属性按照定义的顺序初始化

我们声明一个Child类,拥有两个构造方法:
类的初始化顺序详解_第3张图片
我们在Main类中创建Child的两个对象:
类的初始化顺序详解_第4张图片
输出结果:
类的初始化顺序详解_第5张图片
结论:就算类中属性散乱定义在不同地方,初始化也会严格按照先后顺序执行。

二、属性的自初始化先于构造方法初始化

我们知道,构造方法的主要作用在于初始化类中的成员变量,那么它到底何时执行呢?
在这里,我们在构造函数里将child2引用指向了另一个对象:
类的初始化顺序详解_第6张图片
输出结果如下:
TIM截图20180823121407.png-1.9kB
我们看到,构造函数方法是后被调用的。
结论:构造函数的初始化晚于成员变量自初始化。

三、静态块和静态变量优先

静态方法又被称为类方法,静态属性被称为类域,总是最优先初始化。
静态方法初始化也有两种方法:

  1. 直接初始化
    类的初始化顺序详解_第7张图片
    输出结果:
    类的初始化顺序详解_第8张图片

  2. 采用静态块统一初始化
    类的初始化顺序详解_第9张图片
    输出结果:
    类的初始化顺序详解_第10张图片

两种方法效果一样。但是,注意如果你静态块初始,你一定不能这么做:
类的初始化顺序详解_第11张图片
这样做你是访问不了静态属性的。
你可以这么理解:静态块其实相当于一个属于静态属性的初始化函数,你就算在里面定义了变量,作用周期也括号范围内。所以,你的正确做法是:在外面定义好静态类型的引用而统一在静态块中初始化。

结论:一个类中初始化顺序是:静态->类属性->构造函数。

四、继承关系中的初始化顺序

我们增加一个Parent类:
类的初始化顺序详解_第12张图片
然后让Child继承Paret类,并给Child增加一个静态块:
类的初始化顺序详解_第13张图片
使用Main类调用Child:
类的初始化顺序详解_第14张图片
结果:
类的初始化顺序详解_第15张图片

我们可以看到:Parent和Child的静态块先被调用,之后按照先父类后子类的顺序进行了初始化,而且静态属性只初始化一次
结论:拥有继承关系时,先是从父类到子类初始化静态属性,之后再是从父类到子类初始化非静态属性。


总结

  1. 单个类中初始化顺序:静态属性->非静态属性->构造函数
  2. 继承时初始化顺序:先从父类到子类初始化静态属性,再从父类到子类进行非静态初始工作。
  3. 静态属性都只初始化一次。

你可能感兴趣的:(类的初始化顺序详解)