[总结]初始化过程浅析

1.      加载类(所有的成员变量,无论是否是静态的,都赋了一个默认值)

2.      初始化静态成员变量

3.      初始化非静态类成员变量

4.      调用该类的构造器

 

这是每个类的初始化过程。整个程序的初始化过程,是一个类一个类的完成的;其中,可能加载某个类,但是并没有产生它的实例,也就是说,执行了前两步,但是没有执行34步。

 

示例程序:

class ITest1
{
 static
 {
  System.out.println("Loading ITest1 ... /n");
  }
 public ITest1()
 {
  System.out.println("ITest1's constructor");
  }
 }

class ITest2
{
 static int i=1;
 static int j;
 static
 {
  System.out.println("Loading ITest2 ... ");
  System.out.println("In ITest2:   i="+i+",  j="+j+"/n");
  }
  public ITest2()
  {
   System.out.println("ITest2's constructor");
   }
 }

class ITest3
{
 int i;int j=1;
 boolean b;String s;
 static
 {
  System.out.println("Loading ITest3 ... ");
  }
 public ITest3()
 {
  System.out.println("In ITest3:   i="+i+",  j="+j);  /*如果定义时没有赋初值的话,JVM将赋一个默认值*/
  System.out.println("In ITest3:   b="+b);
  System.out.println("In ITest3:   s="+s);
  }
// public void f(){int i;System.out.println("####"+i);}
 }

public class InitTest extends ITest1
{
 static int j=ITest2.i;
  static
  {
   System.out.println("Loading InitTest ... ");
   System.out.println("In InitTest:   j="+j+"/n");
   }

 public static void main(String[] args)
 {
   System.out.println("Running main() ... ");
   ITest1 it1=new ITest1();
   ITest2 it2=new ITest2();
   System.out.println("After creating it1 and it2, no loading coz only load once ... /n");

       System.out.println("Creating it3 using new ... ...");
   ITest3 it3=new ITest3();

  }
 }

输出结果:

E:/MyDoc/Exercises>java InitTest
Loading ITest1 ...

Loading ITest2 ...
In ITest2:   i=1,  j=0

Loading InitTest ...
In InitTest:   j=1

Running main() ...
ITest1's constructor
ITest2's constructor
After creating it1 and it2, no loading coz only load once ...

Creating it3 using new ... ...
Loading ITest3 ...
In ITest3:   i=0,  j=1
In ITest3:   b=false
In ITest3:   s=null

================================================================================

本程序的执行顺序:

1.      加载类ITest1

2.      初始化ITest1的静态成员变量,如果有的话;

3.      加载类ITest2

4.      初始化ITest2的静态成员变量;

5.      加载InitTest

6.      初始化InitTest的静态成员变量;

7.      找到入口函数main()开始逐句执行;

8.      创建了it1对象,但是由于类ITest1已经加载进来,所以不再重复加载。

9.      初始化ITest1的非静态成员变量,如果有的话;

10.  调用ITest1的构造器;

11.  创建了it2对象,但是由于类ITest2已经加载进来,所以不再重复加载。

12.  初始化ITest2的非静态成员变量,如果有的话;

13.  调用ITest2的构造器;

14.  创建it3对象。

 

it3对象创建过程如下:

1.      加载类ITest3;

2.      初始化其静态成员变量(如果有的话);

3.      初始化成员变量 ijbs

4.      调用ITest3的构造器;

 

=====================================说明========================================

说明1初始化的时候总是先初始化父类,然后初始化子类;而清除(Clean up)的时候顺序正好相反。参见http://blog.csdn.net/fitzwilliam/archive/2006/03/21/630925.aspx

说明2不管创建了多少个实例,类只加载一次。静态成员变量在类加载的时候初始化,同样只初始化一次。

说明3java InitTest 需要把类InitTest加载进JVM。由于类InitTest继承自类Itest1,所以必须先把ITest1加载进来;另外,由于InitTest的静态成员初始化时调用了类ITest2的静态成员变量,所以也必须把ITest2加载进来。

说明4ITest3的加载时间说明JVM并不是在一开始就把程序中所有用到的类都加载进来,而是在某个类被用到的时候才把该类加载进来。“被用到的时候”有两种解释:一是使用new创建了该类的一个实例(如ITest3所示);二是调用了该类的静态变量或者静态方法(如ITest2所示)。

说明5类成员变量(包括静态的)在初始化时,JVM会先赋给它一个默认值(int型为0char为空字符;booleanfalsefloatdouble0.0;引用型为null)。如果在定义时赋了初值就把该初值赋给它;如果定义时未赋初值,在构造器中也未赋初值,就在调用的时候使用默认值。

说明6局部成员变量则必须赋初值,否则如果在程序中调用的话,编译的时候会出错。(如注释掉的f()方法所示。)

 =================================================================================

补充一点:

在类加载的时候,所有的成员变量,无论是否是静态的,都赋了一个默认值。注意,是在类加载的时候赋的,而不是在创建对象(new)的时候。

下面的例子可以证明:

public class Test3 extends Test4
{
    int i=30;
    Test3()
    {
        print();
        i=40;
    }
    public static void main(String[] args)
    {
//        System.out.println(new Test3().i);
        Test4 t4=new Test3();

    }
    void print()
    {
        System.out.println(i);
    }
}
class Test4
{
    int i=10;
   Test4()
    {
        print();
        i=20;
    }
    void print()
    {
        System.out.println(i);
    }
}

OUTPUT:

E:/MyDoc/temp>java Test3
0
30

说明:由于运行时绑定(late-binding),所以创建Test4对象时,Test4的构造器所调用的方法print()是Test3重写后的方法,即Test3中的print()方法;此时,Test3对象还没有创建,所以Test3中的成员变量 i 还没有被初始化,其值为加载时赋的默认值 0.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值