class A
{
    public A()
    {
         System.out.println("aaaaaaaaa");
    }
}
class B
{
    public B()
    {
         System.out.println("bbbbbbbbbbb");
    }
}
class Aa 
{
    private static A a=new A();
    private static B b=new B();
    public Aa()
    {
     System.out.println("111111111");
     f();
    }
    private A aaa=new A();
    
    private void f()
    {
     System.out.println("ffffffffff");
    }
}
public class TestExtend extends Aa{
    public TestExtend()
    {
     super();
     System.out.println("subclass");
    }
    public static void main(String[] args)
    {
     TestExtend test=new TestExtend();
    }

}输出:
aaaaaaaaa
bbbbbbbbbbb
aaaaaaaaa
111111111
ffffffffff
subclass谁来解释下为什么运行结果是这样的?

解决方案 »

  1.   

    class Test
    {
        public Test()
        {
         System.out.println("tttttttttttttt");
        }
    }class Father
    {
    private int i=0;
    private String s="8888888888";
    private Test t=new Test();
        public Father()
        {
         method_1();
         method_2();
         method_3();
         method_4();
        }
        
        protected void method_1()
        {
         System.out.println("method_1");
        }
        protected void method_2()
        {
         System.out.println("method_2");
        }
        protected void method_3()
        {
         System.out.println("method_3");
        }
        protected void method_4()
        {
         System.out.println("method_4");
        }
    }public class SubClass extends Father{
        public SubClass()
        {
         super();  
         method_1();
         method_2();
         method_3();
         method_4();
        }
        protected void method_1()
        {
         System.out.println("method_111");
        }
        protected void method_2()
        {
         System.out.println("method_222");
        }
        protected void method_3()
        {
         System.out.println("method_333");
        }
        protected void method_4()
        {
         System.out.println("method_444");
        }
        public static void main(String[] args)
        {
         new SubClass();
        }
    }
    还有这段代码.都是我写来测试的.
      

  2.   

    对象初始化过程:
        先是static变量和方法(类初始化),由clinit来初始化;
       然后是实例变量,实例模块初始化,构造方法初始化,由init来初始化;
       如果有继承关系,则先执行父类的初始化,然后才是子类的!
      

  3.   

    构造TestExtend 它的时候先构造父类Aa,首先是初始静态的,这时候输出aaa,bbbbbbbb然后还有一个私有的A,又输出aaaaa,然后就是构造函数了,1111111111111111111,然后调用f();就是ffffffffff最后是输出subclass
      

  4.   

    一步一步分析.
    1.从程序的入口开始.
    程序先执行TestExtend test=new TestExtend(); 
    这样就会调用TestExtend的构造方法.
     public TestExtend() 
        { 
        super(); 
        System.out.println("subclass"); 
        } 
    你也看到了,这里调用super();换句话说是调用父类的构造方法.然后是打印"subclass".
    那么程序会先进入父类中执行,最后才会打印"subclass".从这里就知道为什么"subclass"是最后打印出来的了.2.进入到super()后.先会构造那些类的成员对象.然后是自己的构造方法.
    这里静态的有2个a和b.而他们在构造的时候分别打印了"aaaaaaaaa"和"bbbbbbbbbbb"; 
    还有一个aaa.所以会再打印一下"aaaaaaaaa";
    这就是你看到前3个输出的结果.然后Aa 这时再构造它自己,这时打印出"111111111".然后它还调用了"f(); "方法.
    f(); 方法中打印出了"ffffffffff"以上就是整个的过程了.
      

  5.   

    楼主按上面的提示搞清楚程序执行的步骤就好理解了
    另外建议在eclipse进行单步调试,看看程序是怎么执行的
      

  6.   


    class A 

        public A() 
        { 
            System.out.println("aaaaaaaaa"); 
        } 

    class B 

        public B() 
        { 
            System.out.println("bbbbbbbbbbb"); 
        } 

    class Aa 

        private static A a=new A();  //1,aaaaaaaaa     静态域首先执行        
        private static B b=new B();  //2,bbbbbbbbbbb   按顺序
        public Aa() 
        { 
        System.out.println("111111111");  //4,111111111     打印
        f();  //5,ffffffffff    方法调用
        } 
        private A aaa=new A();  //3,aaaaaaaaa     域初始化
        
        private void f() 
        { 
        System.out.println("ffffffffff"); 
        } 

    public class TestExtend extends Aa{ 
        public TestExtend() 
        { 
        super(); 
        System.out.println("subclass");  //6,subclass      打印
        } 
        public static void main(String[] args) 
        { 
        TestExtend test=new TestExtend(); 
        } } 输出: 
    aaaaaaaaa 
    bbbbbbbbbbb 
    aaaaaaaaa 
    111111111 
    ffffffffff 
    subclass 
      

  7.   

    类加载和初始化是两个步骤吧,
    函数体外面的表达试,象
     private static A a=new A(); 
     private static B b=new B(); 
    这些在类加载的时候就被先执行了,优先度很高的,接着再调用构造函数,
    先是基类的再到子类的,
      

  8.   

    这个问题在《thinking in java 》一书中有非常详细的解释。
    主要是class创建时,对成员变量、构造函数等的先后顺序。
      

  9.   

    呵呵,静态属性和父子类加载的问题,经常有人问。建议楼主看一下《thinking in java》中有关Java类加载时的先后顺序。
      

  10.   

    不是吧,这种问题也上这来问,你身边的人呢??SJL吗?幼稚,执行的结果就该这样,妳自己先好好理解一下!java 不是你发明的,对不起你得跟别人学,以后这么幼稚的东西还是。。
      

  11.   

    楼主是对private A aaa=new A(); 这段代码一直想不通吧
    private 是一个访问修饰符,楼主是不是认为,继承关系是子类无法访问父类的private成员的。对,这一点错都没有。问题是这里你并没去通过子类去访问父类。只是你public class TestExtend extends Aa  装载这个类时,JVM会发现这个类是一个子类所以他会去先装载其父类并初始化父类,以便class TestExtend使用。它只是一个初始化问题,初始化问题是跟访问修饰符没关系的。至于初始化顺序,上几楼都说过了。
      

  12.   

    说的太好了 学习了  大看眼界  http://www.pc625.com/index_2.asp?xxpxddd=578947
      

  13.   

    虽然问题比较简单但是自己理解再让让别人说明下其不是理解的跟透彻,不要鄙视别人,其实也许你的问题在高手眼里也是幼稚的!难道你开始学习JAVA的时候什么都懂。
      

  14.   

    还是有个疑问,在TestExtend构造函数里的super()起什么作用了,有没有这句执行结果都是一样的,加这么一句也没有多执行一遍父类的构造函数,这是为什么?
      

  15.   

    super()是使用父类的方法或者属性
      

  16.   

    super();比较特殊。任何类的构造函数中,若是构造函数的第一行代码没有显式的调用super(...);那么Java默认都会调用super();作为父类的初始化函数。
    所以你这里的super();加不加都无所谓。顺便鄙视一下17楼的hhunter,中国不缺少你这种尖酸刻薄的程序员。
      

  17.   

    TestExtend test=new TestExtend(); //这样就会调用TestExtend的构造方法. 
    public TestExtend() 
        { 
        super(); 
        System.out.println("subclass"); 
        } 
    调用super()执行父类的构造方法.然后才是打印"subclass". 
    程序会先进入父类中执行,最后打印"subclass".因为方法要顺序执行嘛
    到父类找构造.先会构造那些父类的成员对象.然后是自己的构造方法. 
    静态的有2个a和b串.而他们在构造的时候分别打印了"aaaaaaaaa"和"bbbbbbbbbbb"; 
    还有一个成员的.所以会再打印一下"aaaaaaaaa"; 
    这就是前3个输出的结果.然后Aa 这时再构造它自己,这时打印出1…….然后它还调用了f()方法. 
    f(); 方法中打印出了"ffffffffff" 
    就这样了
      

  18.   

    比较通用这二楼的观点。另外,thinking in java确实是本好书,lz如果没看过的话,建议楼主看看
      

  19.   

    这个问题不是简单的问题,没什么可鄙视的,况且简单的不能鄙视,学习态度不允许鄙视.
    我相信在类的初始化顺序上面很多人都说不清,还是谦虚学习比较好,
    上面说了很多了,我在补充下,private只是访问权限的控制,子类是会继承父类private的东西的.下面文章可以证明这个事实.只是不能直接访问而已.
    http://blog.csdn.net/sunyujia/archive/2008/06/01/2501709.aspx
      

  20.   

    jvm通过main找到
    TestExtend test=new TestExtend(); 需要将TestExtend载入虚拟机
    TestExtend继承Aa
    所以先将Aa载入虚拟机
    默认状况下先载入Aa的static属性
    执行private static A a = new A();
    新建A的实例调用A的构造器
    System.out.println("aaaaaaaaa");    //aaaaaaaaa
    同上执行private static B b = new B();
    新建B的实例调用B的构造器
    System.out.println("bbbbbbbbbbb");  //bbbbbbbbbbb
    此时虚拟机载入完成接着要创建TestExtend的实例
    public TestExtend() {
      super();
      System.out.println("subclass");
    }
    首先执行super();
    创建父类Aa的实例(若这里没有显示调用super();虚拟机也会隐式调用其父类无参构造器)
    执行构造器实例化之前要先初始化实例变量
    private A aaa = new A();
    执行了System.out.println("aaaaaaaaa"); //aaaaaaaaa
    父类初始化完成
    执行构造器
    public Aa() {
      System.out.println("111111111");    //111111111
      f();                                //ffffffffff
    }
    此时父类实例化完成
    执行子类实例化
    System.out.println("subclass");       //subclass
    通过设置多个断点可以验证以上结论
    可以看出一个简单的实例化并不是真的那么简单 
    只是很多事情jvm隐式的完成了 
    不用我们关心而已
    我们只要记住 初始化的顺序就可以了
    默认情况下 也就是用new来实例化
    执行顺序是先父类后子类
    先static
    然后实例变量
    然后构造器
      

  21.   

    建议看看ThinkInJAVA3中关于类初始化顺序的内容
      

  22.   

    没想到有这么多人回答了,就是程序的执行过程,你向创建了一个Testextends类的对象 在调用她的构造方法时会先调用父类的构造方法,但是Aa里面又又2个静态成员所以先执行,成员的类型时类的对象所以要调用他们的构造函数之后再回到Aa的构造方法执行然后到里面的方法,再到Testextends的构造函数
      

  23.   

    private 修饰的成员变量没又被调用或者继承,只是再执行程序时由于有Static关键字修饰所以要执行,因为她时再类加载前就要执行的,执行了后才会执行类的构造方法...好像是这样的...
      

  24.   

    引用39楼发言通过设置多个断点可以验证以上结论 
    可以看出一个简单的实例化并不是真的那么简单 
    只是很多事情jvm隐式的完成了 
    不用我们关心而已 
    我们只要记住 初始化的顺序就可以了 
    默认情况下 也就是用new来实例化 
    执行顺序是先父类后子类 
    先static 
    然后实例变量 
    然后构造器 
    掌握这点就足够了