分享

java对象的初始化顺序

 臭小子的共享 2015-04-05

java 对象的初始化顺序

 

来源 : http://wenku.baidu.com/view/2631ba717fd5360cba1adb95.html

 

 

对象初始化流程:

  我们根据一段代码来分析对象初始化流程:

/**

 * 基类包含一静态变量、包含一实例变量

 * 包含一个静态初始化块以及一个构造子

 */

class Base{

    public static int a = 10;

    public int b = 20;

    static

    {

        System.out.println("Static Init Base " + a);

        //System.out.println("Null Init " + b);

    }

    public Base()

    {

        System.out.println("Init Base " this.b);

    }

}

/**

 * 一级子类和基类包含的内容一样

 **/

class SuperClass extends Base{

    public static int a1 = getSuperStaticNumber ();

    public int b1 = getSuperInstanceNumber();

    public SuperClass()

    {

        System.out.println("Init SuperClass" this.b1);

    }

    static

    {

        System.out.println("Static Init SuperClass" + a1);

    }

    public static int getSuperStaticNumber()

    {

        System.out.println("Static member init");

        return 100;

    }

    public int getSuperInstanceNumber()

    {

        System.out.println("Instance member init");

        return 200;

    }

}

/**

 * 二级子类为测试该代码的驱动类

 */

public class SubClass extends SuperClass{

    public static int a2 = getStaticNumber ();

    public int b2 = getInstanceNumber();

    public SubClass()

    {

        System.out.println("Init SubClass " + this.b2);

    }

    public static int getStaticNumber()

    {

        System.out.println("Static member init Sub");

        return 1000;

    }

    public int getInstanceNumber()

    {

        System.out.println("Instance member init Sub");

        return 2000;

    }

    public static void main(String args[])

    {

        new SubClass();

    }

    static

    {

        System.out.println("Static Init " + a2);
    }

}

  这段代码会有以下输出:

Static Init Base 10

Static member init

Static Init SuperClass 100

Static member init Sub

Static Init 1000

Init Base 20

Instance member init

Init SuperClass 200

Instance member init Sub

Init SubClass 2000

   [1] 对象在初始化过程, JVM 会先去搜索该类的顶级父类 ,直到搜索到我们所定义的 SubClass 继承树 直接继承于 Object 类的子类,在这里就是 Base

   [2] 然后 JVM 会先加载 Base 类,然后初始化 Base 类的静态变量 a ,然后执行 Base 类的静态初始化块 ,按照这样第一句话会输出: Static Init Base 10 * :此时该类还未调用构造函数,构造函数是实例化的时候调用的】

   [3] 然后 JVM 按照继承树往下搜索,继续加载 Base 类的子类,按照静态成员函数 -> 静态成员变量 -> 静态初始化块 的顺序往下递归,直到加载完我们使用的对象所在的类。

   [4] 类加载完了过后开始对类进行实例化 操作,这个过程还是会先搜索到直接继承于 Object 类的子类,在这里就是 Base

   [5]JVM 会实例化 Base 类的成员函数,然后实例化成员变量,最后调用 Base 类的构造函数;

   [6] 之后, JVM 会递归往继承树下边进行调用,顺序还是遵循: 成员函数 -> 成员变量 -> 构造函数

   [7] 最后直到 SubClass 类的构造函数调用完成

  按照上边书写的逻辑,我们就很清楚了上边源代码的执行结果,而整个 JVM 初始化某个类的流程就是按照以上逻辑进行

  在构造函数调用过程,有几点是需要我们留意的,这里就不提供代码实例,有兴趣的朋友可以自己去试试

   [1] 如果一个类的父类没有无参数构造函数,也就是说父类自定义了一个带参数的构造函数,那么系统不会提供无参数构造函数,此时子类在调用构造函数的时候必须最开始显示调用 super(param) ,因为在构造函数调用之前系统总会先去调用父类的构造函数

   [2] 若一个类定义的时候没有提供构造函数, JVM 会自动为该类定义一个无参数的构造函数

   [3] 一个类在调用构造函数的时候, JVM 隐藏了一句代码 super() ,前提是父类未定义构造函数或者显示定义了无参构造函数;其含义就是调用父类的构造函数,如果父类的无参数构造函数被覆盖的话需要在子类构造函数中显示调用父类带参数的构造函数

   [4] 当类中的成员函数遇到变量的时候,会先根据变量名在函数域即局部变量范围内去寻找该变量,如果找不到才会去寻找实例变量或者静态变量,其意思可以理解为局部变量可以和实例变量或者静态变量同名,而且会在函数调用过程优先使用,这个原因在于在函数范围内,如果调用的变量是实例变量,其中前缀 this. 被隐藏了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多