class Bowl {
     Bowl(int er){
         System.out.println("Bowl(" + er + ")");
  }
     void f(int er){
         System.out.println("f(" + er + ")");
     }
  }
class Table {
      static Bowl b1 = new Bowl(1);
      Table(){
      System.out.println("Table()");
      b2.f(1);
   }
      void f2(int er){
          System.out.println("f2(" + er + ")"); 
    }
       static Bowl b2 = new Bowl(2);
 } 
class Cupboard {
      Bowl b3 = new Bowl(3);
      static Bowl b4 = new Bowl(4);
      Cupboard(){
      System.out.println("Cupboard()");
      b4.f(2);
    } 
      void f3(int er){
      System.out.println("f3(" + er + ")");
    }    
      static Bowl b5 = new Bowl(5);
 }
public class StaticInitialization {
       public static void main(String args[]){
              System.out.println("Creating new Cupboard() in main");
              new Cupboard();
              System.out.println("Creating new Cupboard() in main");
              new Cupboard();
              t2.f2(1);
              t3.f3(1);
        }
              static Table t2 = new Table();
              static Cupboard t3 = new Cupboard();
    }  
----------------------------------------------------------------------------------------
//程序运行的结果
Bowl(1)
Bowl(2)
Table()
f(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f(2)
f2(1)
f3(1)
------------------------------------------------------------------
这是一个静态数据初始化的例子。
但是我有几个疑问。
(1)JAVA在找到main()方法之前,是先对类初始化还是先对类中的对象初始化?
换句话说,类的初始化是在main()方法之前进行马?
          对象的初始化是在main()方法之后进行?
(2)看这个程序,人们都说java中,main()方法是入口,按照这样来说,找到main()之后,因该执行
System.out.println("Creating new Cupboard() in main"),输出Creating new Cupboard() in main,然后再调用无参的构造方法Cupboard(),然后再为Bowl()构造方法分配空间,把er==3赋上去,执行System.out.println()语句,输出Bowl(3).....等等,这样执行下去
但是程序的实际运行结果不是这样的。我想知道程序的正确的解释思路。
我想知道这是为什么。因为我认为,中国的软件行业缺少这种人,弄清楚程序内部是怎么样来做的很多都是会用,但是却说不出道理来。
所以,希望大家给指点指点

解决方案 »

  1.   

    已经有人问过这个问题了执行StaticInitialization的main方法也就是初始化该类,该类中有两个静态变量b2和t3,所以先执行静态变量的初始化
      

  2.   

    想知道程序实际的执行顺序,找个调试器(比如 Eclipse),单步走一遍再清楚不过了。想知道为什么是这样的执行顺序,那就去看《Java Language Specification》。
      

  3.   

    对于类的初始化顺序,结合你的例子,我认为如下:静态成员变量最先初始化,只要类被调用(不包括new对象)其次是static代码块如果new对象,则先调用父类构造方法(如果有继承的话),然后初始化该对象的成员变量(非静态的),最后调用自己的构造方法一个简单的例子class t7
    {
        public t7()
        {
            System.out.println("father construct....");
        }
    }
    public class Test7 extends t7
    {
        public Test7()
        {
            System.out.println("construct....");
        }
        static String a = "aaaa";
        int i = 123;
        
        static
        {
            System.out.println("static ....");
        }
        public static void main(String[] args)
        {
            Test7 t = new Test7();
            System.out.println("Test");
        }
    }程序的执行顺序是这样的:
    main方法是Test7类的,因此先初始化Test7的静态成员a, 其次执行static块,然后进入main方法,创建Test7对象t,由于Test7是继承自t7,因此先执行其父类的构造方法,然后执行自己的构造方法,而该对象有非静态成员i,因此,再执行自己的构造方法之前,还要初始化非静态成员变量i,最后执行构造方法你的例子也这么分析,就知道前前后后的顺序了
      

  4.   

    class Bowl {
         Bowl(int er){
             System.out.println("Bowl(" + er + ")");
      }
         void f(int er){
             System.out.println("f(" + er + ")");
         }
      }
    class Table {
          static Bowl b1 = new Bowl(1);
          Table(){
          System.out.println("Table()");
          b2.f(1);
       }
          void f2(int er){
              System.out.println("f2(" + er + ")"); 
        }
           static Bowl b2 = new Bowl(2);
     } 
    class Cupboard {
          Bowl b3 = new Bowl(3);
          static Bowl b4 = new Bowl(4);
          Cupboard(){
          System.out.println("Cupboard()");
          b4.f(2);
        } 
          void f3(int er){
          System.out.println("f3(" + er + ")");
        }    
          static Bowl b5 = new Bowl(5);
     }
    public class StaticInitialization {
           public static void main(String args[]){
                  System.out.println("Creating new Cupboard() in main");
                  new Cupboard();
                  System.out.println("Creating new Cupboard() in main");
                  new Cupboard();
                  t2.f2(1);
                  t3.f3(1);
            }
                  static Table t2 = new Table();
                  static Cupboard t3 = new Cupboard();
        }  
    ---------------------------------------------------------------------------------
    我把此程序打了15个点,发现程序解释的顺序很乱
    1.在Bowl类里System.out.println("Bowl(" + er + ")");
    2.Bowl里,f()方法里,System.out.println("f(" + er + ")");
    3.在Table里,static Bowl b1 = new Bowl(1);
    4.Table()构造方法
    5.Table()里的b2.f(1);
    6.Table类里f2()方法
    7.Table类里static Bowl b2 = new Bowl(2);
    8.Cupboard类里Bowl b4 = new Bowl(4);
    9.Cupboard()里b4.f(2)
    10.Cupboard类里static Bowl b5 = new Bowl(5);
    11.main()里t2.f2(1);
    12.main()里t3.f3(1);
    13.main()里static Table t2 = new Table();
    14.main()里static Cupboard t3 = new Cupboard();
    15.Cupboard类里的Bowl B3 = new Bowl(3);
    然后看是用eclipe执行。
    奇怪的是程序首先解释的是Bowl类里的System.out.println("Bowl(" + er + ")");语句
    然后开始解释Table类里的static Bowl b1 = new Bowl(1);
    然后再解释是Bowl类里的System.out.println("Bowl(" + er + ")");。
    接下来的是static Bowl b2 = new Bowl(2);
    然后直接跳过Bowl类里的System.out.println("Bowl(" + er + ")");
    -------------[这点我很是纳闷,为什么会直接跳过这个语句,更奇怪的是还输出了Bowl(2)]
    下面是执行Table类里的Table()构造方法-----[这点也很奇怪,程序当中还有b4,b5这两个静态的变量,怎么会不执行],
    然后在Table()里的b2.f(1)绕了2次
    接下来执行的是Bowl里,f()方法里,System.out.println("f(" + er + ")");
    然后再跳到main()里static Table t2 = new Table();
    接下来执行的是在Bowl类里System.out.println("Bowl(" + er + ")");
    接下来执行的是8.Cupboard类里Bowl b4 = new Bowl(4);
    然后又回到Bowl类里System.out.println("Bowl(" + er + ")");
    接下来是Cupboard类里static Bowl b5 = new Bowl(5);
    接下来的是在Bowl类里System.out.println("Bowl(" + er + ")");
    然后是Cupboard类里的Bowl B3 = new Bowl(3);
    接下来的是在Cupboard()里b4.f(2)里转了2次
    然后是Bowl里,f()方法里,System.out.println("f(" + er + ")");
    然后到main()里static Cupboard t3 = new Cupboard();
    还有11部。。
    ----------------------------------------------------------------------
    我画的图很乱,现在看不懂了。
    明天继续。。
    主要把前7布看看就好了。
    因为这各程序的第一步就很奇怪,为什么会先解释Bowl类里的System.out.println("Bowl(" + er + ")");语句???
    顶!!!
      

  5.   

    怎么不顶???kevin的方案作了。
    但是按照他的顺序分析。不对。
    用eclipse,第一步就执Bowl类里Bowl()方法里的System.out.println("Bowl(" + er + ")");
    然后才是按照kevinliuu所设想的,按照先初始化静态的变量,先初始b1,然后调用Bowl类里Bowl()方法里的System.out.println("Bowl(" + er + ")");
    然后再初始b2,但是问题出现了,下面按照我们预想的,应该会掉用Bowl类里Bowl()方法里的System.out.println("Bowl(" + er + ")");,但是我们错了。程序在这个时候直接跳过Bowl类里Bowl()方法里的System.out.println("Bowl(" + er + ")");方法,
    然后输出Bowl(2)...
    下面也是很奇怪,不初始化b4,b5...
    而是输出Table类里的Table()方法
    很多的疑问。。
    希望大家能一起把他解决掉!!!
      

  6.   

    ...........你还是没明白我的意思我就再耐心的给你讲一下第一句是如何打印的public class StaticInitialization {
    public static void main(String args[]){
    System.out.println("Creating new Cupboard() in main");
    new Cupboard();
    System.out.println("Creating new Cupboard() in main");
    new Cupboard();
    t2.f2(1);
    t3.f3(1);
    }
    static Table t2 = new Table();
    static Cupboard t3 = new Cupboard();

    这个类是入口类,先执行static Table t2 = new Table(); //静态成员先初始化
    进入Table类
    class Table {
    static Bowl b1 = new Bowl(1);
    Table(){
    System.out.println("Table()");
    b2.f(1);
    }
    void f2(int er){
    System.out.println("f2(" + er + ")");
    }
    static Bowl b2 = new Bowl(2);

    同样的原理 static Bowl b1 = new Bowl(1); //先初始化b1,进入Bowl类
    class Bowl {
    Bowl(int er){
    System.out.println("Bowl(" + er + ")");
    }
    void f(int er){
    System.out.println("f(" + er + ")");
    }
    }
    由于Bowl没有静态成员,所以直接调用构造方法,因为上面是new一个Bowl对象,并且带参,所以调用Bow(int er)构造方法,打印  Bowl(1)自己慢慢分析吧
    另外,分析透彻再来讲讲,不要轻易的相信自己,也不要轻易的否定别人