java初始化LinkList JAVA初始化对象API_初始化

验证:确保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中进行反射操作的方法会被初始化。

对象实例化:

  1. 先调用父类的构造函数(在子类中会有显示调用super和隐式调用)。
  2. 初始化类中实例域的值,按照代码出现的顺序依次执行。
  3. 然后子类构造方法中其他的代码。

注意:子类构造方法中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 。
  • 最后完成

更详细的流程:

  1. 进入Derived 构造函数。
  2. Derived 成员变量的内存被分配。
  3. Base 构造函数被隐含调用。
  4. Base 构造函数调用preProcess()。
  5. Derived 的preProcess 设置whenAmISet 值为 “set in preProcess()”。
  6. Derived 的成员变量初始化被调用。
  7. 执行Derived 构造函数体

java初始化LinkList JAVA初始化对象API_初始化_02

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