您的位置:首页 > 编程语言 > Java开发

java对象的初始化顺序

2011-03-25 16:49 344 查看
对象初始化流程:

  我们根据一段代码来分析对象初始化流程:
/**
* 基类包含一静态变量、包含一实例变量
* 包含一个静态初始化块以及一个构造子
*/
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. 被隐藏了。
转自:http://wenku.baidu.com/view/2631ba717fd5360cba1adb95.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: