public class A {
public A() {
init();
}

protected void init() {

} public void print() {
System.out.print("1");
}

}
public class B extends A{
private String b1=null;
protected void init() {
this.b1 = "0";
print();
}
public void print() {
// TODO Auto-generated method stub
System.out.print(b1);
}
        public static void main(String[] args) {
// TODO Auto-generated method stub
A a =new B();
a.print();
}

}
结果是0null why?
面试题

解决方案 »

  1.   

    跟C++不同,父类的构造函数调用不是自动的。所以A的init()没有被调用过。
    显示调用:
    class B extends A {
      private String b1 = null;  //注意这里
      public B() {
        super();
      }  protected void init() {
        this.b1 = "0";
        print();
      }  public void print() {
        System.out.print(b1);
      }  public static void main(String[] args) {
        A a = new B();
        a.print();
      }
    }
    另外下次发帖记得用代码块高亮功能,不然看着很累
      

  2.   

    为什么a.print()是null啊 b不是赋值”0“了吗
      

  3.   

    A a = new B();
    调用父类的构造方法
    public A() {
    init();
    }
    执行其中的init();时,因子类重写了该方法,所在实际上执行的是子类B的init()方法
    于是,输出0
    再执行B类的构造方法
    接着初始化B类的成员private String b1 = null;
    再接着执行a.print();,此时执行的是B类重写的print()方法
     public void print() {
        System.out.print(b1);
      }
    于是输出了null
    不知道我说清楚没有。
      

  4.   

    0是new B()时调用父类的构造函数时输出的 null是调用a.print()时输出的
    我想既然输出的不一样,应该输出的b值属于不用的实例对象一个是子类一个是父类
    我感觉我这么想是错误的 但是我也只能想到这里了 我刚学java不久
      

  5.   

    B的默认构造函数public B() {
        super();
      }
    调用完super()之后还会调用private String b1 = null;这条语句么
      

  6.   

    在执行A a =new B();时程序会先调用父类的构造,执行init();方法,而实际执行的是子类的init();方法(当子类复写了父类的方法,那么程序执行的永远是子类复写的方法)所以输出0,
    再执行a.print();而调用的还是子类复写的print();方法,所以输出null,
    在这里有一个误区,即调用父类的构造时,执行init();方法中的b1并非是执行a.print();时的b1,这两个b1不是同一个属性,所以虽然在执行A a =new B();时以为b1赋值0,但并不影响执行a.print();时的b1的值,
    public class B extends A{
    private String b1="Hello World";
    protected void init() {
    //this.b1 = "0";
    print();
    }
    public void print() {
    // TODO Auto-generated method stub
    System.out.print(b1);
    }
            public static void main(String[] args) {
    // TODO Auto-generated method stub
    A a =new B();
    a.print();
    }}
    输出:nullHello World
    在以上的程序中,我把init()方法中的赋值语句不要,输出的b1为null,而并非是Hello World,而执行a.print();时输出Hello World,所以这两
    个b1并不是同一个属性,
      

  7.   

    执行init();方法中的b1并非是执行a.print();时的b1,这两个b1不是同一个属性 这是什么意思 
    那这个this.b1是什么呢
      

  8.   

    在我的程序中,去掉中的this.b1 = "0";语句,当实例化a是调用A的无参构造,执行直接打印b1(System.out.print(b1);),执行a.print();时也是直接打印b1,但输出的结果不一样,所以这两个b1不是同一个b1,但this是同一个(都是a),在执行第一个b1时,由于一个b1是在实例化a时由A类的无参构造调用,所以在打印这个b1时,程序并不能找到B类中的private String b1="Hello World";语句,而第二个b1是由实例化后的a直接调用print();方法执行的,它打印的就是由private String b1="Hello World";语句赋值好的b1,在这里,关键的是init();方法是由A类的无参构造调用,所以在执行这个方法时对b1作的一切操作都不会影响到B类中的b1的本身,如果把init();方法放在B类的构造中情况就不一样了,那么输出的就是00了,
    不知道这样的解释是否清楚,
      

  9.   


    我擦,我先自抽9999999下。误人子弟,大罪无边。
    A.super() 是隐式调用的,就是被new B();自动调用的。其他的楼上解释过了。。
      

  10.   

    dbug走一下,看看怎么执行的。。
      

  11.   

     A a = new B(); 
     会调用父类的构造方法,因为父类构造方法中调用了init方法,但是子类复写了init方法所以调用了子类的init方法。子类init中调用print方法也是调用的子类中的。。b1在子类的init方法中被赋值为0.所以会输出0.。
     在执行完父类构造函数的时候会执行到 private String b1=null; 所以此时b1=null了。
      a.print();
     执行依然是子类复写了的print方法。。所以这个地方就输出null咯。
      

  12.   

    各位楼友说的很清楚了,楼主把他们的整理下,知识是慢慢积累的。我最近培训完java,我们可以交流下
      

  13.   

    继承情况下类的初始化顺序
    1.父类静态变量
    2.父类静态块
    3.子类静态变量
    4.子类静态块
    5.父类非静态变量
    6.父类非静态块
    7.父类构造函数
    8.子类非静态变量
    9.子类非静态块
    10.子类构造函数由于在父类构造函数(7)中调用子类覆盖的方法init,B类中b1被赋值为0,这个没问题。
    在子类非静态变量初始化的时候(8),b1又被重新赋值为null,所以在语句A a =new B();
    执行完之后,B类中b1的值为null.
    所以结果为0null
      

  14.   

    b1=0是在对象a构造的过程中赋值的  这个时候对象a其实还没有生成  b1有点像构造方法中的内部参数因此等对象a生成后再去调用b1显示null
      

  15.   

    B的默认构造函数public B() {
        super();
      }
    调用完super()之后还会调用private String b1 = null;这条语句么自己 debug下!
      

  16.   

    很清楚了……我跟LZ的疑惑差不多,第一个0能明白,但是对前后两个b1不是同一个还是没理解透彻……学习了!