类和对象的初始化
类的初始化
1)类的初始化阶段是类加载过程的最后一个步骤。
类加载过程即加载、 验证、 准备、 解析和初始化。
2)直到初始化阶段, Java虚拟机才真正开始执行类中编写的Java程序代码, 将主导权移交给应用程序。
3)**根据程序员的要求去真正初始化类变量和其他资源。**和前面准备阶段不一样。
4)初始化阶段就是执行类构造器**< clinit >()方法**的过程。
< clinit >()方法介绍:
1)所有的类变量初始化语句(显示赋值)和类型的静态初始化器
在static语句块中使用到静态变量时一定要将该静态变量的声明语句放在static语句块的前面, 否则会发生illegal forward references的编译错误
2)< clinit >()方法与类的构造函数(即在虚拟机视角中的实例构造器<init>()方法
) 不同, 它不需要显
式地调用父类构造器, Java虚拟机会保证在子类的<clinit>()方法
执行前, 父类的<clinit>()方法
已经执行完毕。
3)由于父类的<clinit>()方法
先执行, 也就意味着父类中定义的静态语句块要优先于子类的变量赋值
操作 。
为什么初始化子类需要先初始化父类:
从理论上来说,既然你要初始化子类,子类会继承父类的一部分属性和方法,如果你不初始化父类,那么子类就没有意义。继承不了父类的属性和方法。
注意: 并非所有的类都会拥有一个<clinit>方法, 满足下列条件之一的类不会拥有<clinit>方法:
该类既没有声明任何类变量,也没有静态初始化语句;
该类声明了类变量,但没有明确使用类变量初始化语句或静态初始化语句初始化;
该类仅包含静态 final 变量的类变量初始化语句,并且类变量初始化语句是编译时常量表达式;
初始化顺序
重点是分清<clinit>
方法和<init>
方法。
1.类的初始化
前置知识:
1)一个类要创建实例,要先加载并先初始化这个类。
2)子类初始化要先初始化父类
3)类的初始化由<clinit>()方法
实现。
类的初始化顺序:
1)初始化父类
2)初始化自己(执行类变量赋值语句和静态代码块)
2.对象初始化(构造方法)
前置知识:
1)创建一个类的对象之前,必须先进行类的初始化。
2)<init>()方法
首行是super(),即父类的<init>()方法
。
所以,创建一个子类实例过程为:
1)初始化子类(先初始化父类)
2)执行子类<init>()方法
(先执行父类<init>()方法
)
<init>()方法
:由非静态实例变量显示复制代码和非静态代码块、对应的构造器代码组成,并顺序执行,只执行一次
综上,对象初始化顺序为:
先初始化父类的静态代码—>初始化子类的静态代码–>初始化父类的非静态代码—>初始化父类构造函数—>初始化子类非静态代码—>初始化子类构造函数