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

class Test4 

    int i=10;    Test4()
    {
        print();
        i=20;
    } 
    void print()
    {
        System.out.println(i);
    }
} 输出结果:
0 //这里,为什么是0而不是10?
30
40
Press any key to continue...这个程序是怎样执行的?

解决方案 »

  1.   

    因为没有new Test4(),没有实例化一个test4,就没有给i复制10
      

  2.   

    不是,是调用了test3.print()  而不是test4.print()
      

  3.   

    System.out.println(new Test3().i);当然先从这开始,在new Test3()时候,会先调父类的构造函数
    Test4()
        {
            print();
    在调父类print()方法时因为子类从重了此方法,所以又会去调子类的
      void print()
        {
            System.out.println(i);因为这个时候i只在父类中=10并没有在子类中被赋值所以第一次打印是0;
        } 
    继续运行父类构造函数i=20;
    运行完父类构造函数会去运行子类的i=30;再运行字类构造函数
    Test3()
        {
            print();
    再次调用子类print()方法打印出30;
            i=40;
        } 
    最后执行完整的System.out.println(new Test3().i);打印出40我的理解是这样
      

  4.   

    因为从头到尾也没有产生Test4对象!
    即使产生一个Test4对象,第一行输出的还是0。
    因为JAVA编译器保证所有变量在函数被调用前必须被初始化,
    即使你在变量定义处给定了初始值,对于int来说,它还是会被赋初始值0试着将
        Test3()
        {
            print();
            i=40;
        } 
    改为
        Test3()
        {
            super.print();
            i=40;
        } 
    看看结果是什么!
      

  5.   

    更正一下我刚才说的,
    在new Test3()时候,确实会先调父类的构造函数
    但这不是重点,重点是
    JAVA编译器保证所有变量在函数被调用前必须被初始化
      

  6.   

    首先:要弄明白构造方法的执行顺序
        任何一个类都会有一个默认的执行方法 <init> 也就是构造方法,上边Test3调用构造方法时同时也调用Test4的默认构造方法。其次:非静态成员变量在默认构造时(初始化),会被赋予默认值,也就是说 实际上是调用了Test4的构造方法,但这个构造方法是一个副0值得构造方法 <init>。最后:代码的执行顺序 1 -> 运行程序 执行 Test3的 main方法
          System.out.println(new Test3().i);
     2 -> 构造Test3的匿名对象 调用 Test3的构造方法
          Test3的构造方法首先执行父类Test4的默认构造方法 所有成员对象值为 0 或者 空 null
     3 -> 继续执行Test3的构造方法
      

  7.   

    我们做个简单的侧试大家一看就明白了
    public class Test3
        extends Test4 {
      int i = 30;
      Test3() {    System.out.println(i);
        print();
        System.out.println("33333333333333");
        i = 40;
      }  public static void main(String[] args) {
        System.out.println(new Test3().i);
        System.out.println("111111111111111");
      }  void print() {
        System.out.println("222222222222222");
        System.out.println(i);
      }
    }class Test4 {
      int i = 10;
      Test4() {
        System.out.println(i);
        System.out.println("44444444444444");
        print();
        System.out.println("55555555555555");
        i = 20;
        System.out.println(i);
      }  void print() {
        System.out.println("6666666666666");
        System.out.println(i);
      }
    }
    下面是输出的结果:
    10444444444444442222222222222220555555555555552030222222222222222303333333333333340111111111111111
    从以上的结果不难看出程序运行的先后,和i值的变化,不用我说一看就明白