先看下面的程序:package c05.net;class Bowl {
 Bowl(int er) {
 System.out.println("Bowl(" + er + ")");
 } void f1() {
 System.out.println("Ok");
 }
 } class Cupboard {
 Bowl b1 = new Bowl(1); static Bowl b2 = new Bowl(2); Cupboard() {
 System.out.println("Cupboard()");
 } static Bowl b3 = new Bowl(3);
 } class Table {
 Table() {
 System.out.println("Table()");
 }
 Table(String a,int i){
 this();
 System.out.println("Ok");
 }
 } public class Order {
 static Cupboard t1 = new Cupboard(); static Table t2; Bowl t3 = new Bowl(10); void print() {
 t3.f1();
 } public static void main(String[] args) {
 System.out.println("Creating new Cupboard() in main");
 new Cupboard();
 System.out.println("Creating new Cupboard() in main");
 Order od = new Order();
 od.t3.f1();
 Table t4 = new Table("aa",1);
 }
 }运行结果:Bowl(2)
Bowl(3)
Bowl(1)
Cupboard()
Creating new Cupboard() in main
Bowl(1)
Cupboard()
Creating new Cupboard() in main
Bowl(10)
Ok
Table()
Ok
分析:首先程序从public类开始,装载Order,class,运行static Cupboard t1 = new Cupboard();由于t1是一个对象引用变量,首先得到初始化,然后转到Cupboard类的实例中,这时候程序开始初始化该实例中的变量,按照先static后非static变量初始化的顺序原则开始初始化各个变量,此时, static Bowl b2 = new Bowl(2);static Bowl b3 = new Bowl(3);
这两块先得到初始化然后   Bowl b1 = new Bowl(1);得到初始化(注意,这是非stataic变量)然后转到Cupboard() 构造函数。此时Cupboard类已经初始化完毕,程序返回到public类中,又发现有 static Table t2;开始初始化,由于t2只是个声明的变量,并没有创建一个Table对象让它指向,因此不要管这个t2变量。在public类中,由于此时再没有static变量可以初始化,那么程序转到static方法main中进行,(注意:Bowl t3 = new Bowl(10); 这一句为什么得不到初始化,是因为此时没有创建类Order的实例,所以程序目前还不会初始化该代码,至于以后会不会初始化,还要看在main方法中是否会创建Order类的实例,如创建了,则一定初始化,否则不会。)在main方法中, System.out.println("Creating new Cupboard() in main");//首先打印该行要输出的语句
 new Cupboard();  //创建了Cupboard类的实例,程序转到Cupboard中进行变量初始化,此时要注意:    static变量的初始化,它只能初始化一次,也就是说,如果前面已经初始化过了,那么此时就不必要再初始化了,这一点要牢记!!!
 System.out.println("Creating new Order() in main");//程序转入此行打印要输出的语句
 Order od = new Order();//创建Order对象实例,程序转入实例od中,此时Bowl t3 = new Bowl(10);这一句的t3会得到初始化,程序转到Bowl类中进行有关的操作,操作完后返回到main方法中
  od.t3.f1();  //调用实例t3中的方法f()
 Table t4 = new Table("aa",1); //创建Table类的实例,让t4指向这个实例,t4得到初始化,调用Table含有参数的构造方法,程序进行下去。这样就完成了对这个程序的真个的流程的分析,如果有错误的地方,或者还要补充的地方,还希望大家指点一下,谢谢!!!

解决方案 »

  1.   

    谢谢
    很实用
    终于明白static的用法
      

  2.   

    这不是Thingking in Java中的例子么?的确很经典的。
      

  3.   

    补充一个,如果有this()这样调用构造方法的话,该语句在非静态初始化之前执行。
      

  4.   

    那怎么解释以下这个程序呢?
    【程序】
    // 程序1
    class Singleton {
      private static Singleton obj = new Singleton();
      public static int counter1;
      public static int counter2 = 0;
      private Singleton() {
        counter1++;
        counter2++;
      }
      public static Singleton getInstance() {
        return obj;
      }
    }// 程序2
    public class MyMain {
      public static void main(String[] args) {
        Singleton obj = Singleton.getInstance();
        System.out.println("obj.counter1=="+obj.counter1);
        System.out.println("obj.counter2=="+obj.counter2);
      }
    }执行结果是:
    obj.counter1==1
    obj.counter2==0 
      

  5.   

    个人猜测仅供参考首先,3个静态成员进行默认初始化
    obj为null
    counter1为0
    counter2为0然后进行变量定义处的初始化obj这个执行new Singleton(),这时counter1与counter2均变为1
    counter1这行没有语句
    counter2又被置为0至此 counter1为1 counter2为0
      

  6.   

    其实这个问题这样考虑就行了:静态变量的初始化只会进行一次。
    对于count1,由于在定义时没有显示赋值初始化,这时系统会默认给它一个值为0,然后构造函数里再进行初始化,0自增得1
    对于count2,由于定义时候有了初值,就已经初始化了,构造器中的语句便失效了
    package thinkinjava3;//程序1
    class Singleton {
      private static Singleton obj = new Singleton();
      public static int counter1;
      public static int counter2 = 0;
      private Singleton() {
      counter1=2;
      counter2=2;
      }
      public static Singleton getInstance() {
      return obj;
      }
    }// 程序2
    public class MyMain {
      public static void main(String[] args) {
      Singleton obj = Singleton.getInstance();
      System.out.println("obj.counter1=="+obj.counter1);
      System.out.println("obj.counter2=="+obj.counter2);
      }
    }用以上代码测试也能看出结果