class Sup{
    private int i=2;
    public Sup(){
        this.foo();
    }
    public  void foo(){
    System.out.println(i);
}
    
}
public class test1 extends Sup{
    private int i=22;
    public test1(){
    //System.out.println("hello");
    i=222;
    }
    public  void foo(){
    System.out.println(i);
}
    public static void main(String args[]){
    new test1();
    //
}
}
没人理我&……哎,我发帖我!!这个输出为什么是0???

解决方案 »

  1.   

    胡乱分析一下这个原因
    子类的构造函数会默认首先调用父类的同名构造函数
    因此,在test1()构造时会先super();
    而父类的构造函数中有这样的语句:this.foo();
    意义是调用当前引用的foo方法
    当前引用正是new出来的test1的一个对象
    实际上调用的是test1中的foo方法
    而在子类执行完父类的构造方法之前,是不会进行自身的构造的
    而test1中的i这个时候还没有初始化
    所以出现了这种情况
      

  2.   

    可以在main中打个断点,跟踪进去看看!
    其执行顺序是在test1的构造方法中调用Sup的构造方法->初始化Sup的i->this.foo();(这句代码执行的时候调用的是test1的foo方法,就是多态,此时test1的i还没有显示初始化,其默认为0,所以打印为0)->初始化test1的i(此时test1的i为22)->执行test1的构造方法(此时test1的i为222)。
      

  3.   

    这怎么看怎么觉得好像是我发的程序啊~~兄弟是不是从论坛上面弄下来的啊?这个程序是这样的当调用test1()构造方法的时候首先会默认调用父类的无参构造方法
    然后现在Sub()构造方法其实调用的是test1类中的foo()方法,为什么会是这样呢?
    因为用了this这个关键字,而这个关键字是表示现在正在初始化的那个类,也就是test1类中的foo方法
    现在,会发现这个类是要覆盖父类的方法,也System.out.println(i);
    而问题就在这里了,这个i是哪里的i,答案是test1中的i,而这个i的初始值是0
    为什么是0呢,必须知道的是  
    只有在一个类初始化(也就是构造方法完成)完成之后才会对普通类型的进行初始化(也就是赋值222)
    而对于类变量(static类型的)会在初始化(也就是构造方法完成)之前赋值,所以可以看到这里的i显然还没有赋值222  因为还没有初始化完成呢
    所以就输出了0 了不知道这么说你懂不懂了
      

  4.   


    这个程序是要绕很多弯子  其实正是这样的题才勾起了我学java的兴趣  
    以前一直觉得java简单   学多了就觉得不那么简单  特别是关于内存  关于地址
    要是深挖的话不比C语言简单。。
      

  5.   

    子类会先调用父类的构造方法,
    而你父类的构造方法是this.foo();
    这个this是你子类的实例,所以他调用的不是父类Sup里的foo()方法而是子类里的foo()方法 
    此时子类的构造方法没执行(没初始化),所以输出的i是0;
      

  6.   


    本来就是啦, 在那边吼了一下,没人理我,不得已贴出来了,嘻嘻 private   int i=22;
        public test1(){  }这当中的i不起作用吗??在前面加个private static  int i=22;结果就显示22了呀。
      

  7.   

    你可以在Text1中 把private int i=22;
    改成private static int i = 22;
    运行结果就是22了
      

  8.   

    public Sup() {
    this.foo();
    }
    这个方法调用的是子类Text1中的
    public void foo() {
    System.out.println(i);
    }方法