验证:确保java类的字节码表示在结构上完全正确。验证过程中有可能导致其他java类或者接口被加载。
若验证过程中发现字节码格式不正确,会抛出java.lang.verfiyError异常。一般通过java编译器生成的字节码不会出现验证错误。
解析:处理所加载的java类中包含的形式引用。
初始化:主要执行java类中的静态代块和初始化静态域。
初始化过程中静态代码快和静态代码域按照在代码中 出现的顺序依次执行。
示例:
public class staticOrder{
public static int x = 10;
public static int y = 2 0 * x;
static{
x = 30;
}
public static void main(String args[]){
System.out.println(y); //结果是200
}
}
初始化何时才会发生???
- 实例化java类时,即使用new关键字
- 调用java类中的静态方法。
- 为类和接口中的静态域赋值。
- 访问类或接口中的声明的静态域,并且该域不是常量。
- 调用Class类和反射API中进行反射操作的方法会被初始化。
对象实例化:
- 先调用父类的构造函数(在子类中会有显示调用super和隐式调用)。
- 初始化类中实例域的值,按照代码出现的顺序依次执行。
- 然后子类构造方法中其他的代码。
注意:子类构造方法中super()可以省略。但是必须放在子类中的第一行。
任何子类的构造方法(有参或无参)若没有显示调用父类构造方法即super(参数),在java中都会隐式调用super();
下面是来自 酷壳--陈皓 的《Java构造时成员初始化的陷阱 》博客的例子:
publicclass Base{
Base() {
preProcess();
}
voidpreProcess() {}
}
publicclass Derived extends Base{
publicString whenAmISet = "set when declared";
@Overridevoid preProcess(){
whenAmISet = "set in preProcess()";
}
}
如果我们构造一个子类实例,那么,whenAmISet 的值会是什么呢?
publicclass Main{
publicstatic void main(String[] args){
Derived d = new Derived();
System.out.println( d.whenAmISet );
}
}
运行结果是:set wher declared
why??????
根据上面我们说道;
- 先调用子类的构造方法,
- 第一行是隐式super(),调用父类构造方法。在这里实例域 whenAmIset 调用函数preProcess 被赋值set in preProcess()。(这里调用的preProcess是子类的函数,不是父类中的函数)
- 然后在初始化实例域;whenAmIset 又被赋值为set wher declared 。
- 最后完成
更详细的流程:
- 进入Derived 构造函数。
- Derived 成员变量的内存被分配。
- Base 构造函数被隐含调用。
- Base 构造函数调用preProcess()。
- Derived 的preProcess 设置whenAmISet 值为 “set in preProcess()”。
- Derived 的成员变量初始化被调用。
- 执行Derived 构造函数体
public class test {
public static void main(String[] args) {
SuperInitField p = new SuperInitField(); //-------------------- 第一行
SuperInitField c = new SubInitField();
}
}
class SuperInitField {
public SuperInitField() {
System.out.println("parent");
}
static {
System.out.println("static parent");
}
}
class SubInitField extends SuperInitField {
public SubInitField() {
System.out.println("child");
}
static {
System.out.println("static child");
}
}
运行结果: static parent
parent
static child
parent
child
假设将 第一行注释掉
结果又是什么呢?
答案:
static parent
static child
parent
child