当前位置:编程学习 > JAVA >>

求解一道面试题

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?
面试题 类 --------------------编程问答-------------------- 跟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();
  }
}

另外下次发帖记得用代码块高亮功能,不然看着很累 --------------------编程问答--------------------
引用 1 楼 lcf 的回复:
跟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();
  }
}

另外下次发帖记得用代码块高亮功能,不然看着很累
为什么a.print()是null啊 b不是赋值”0“了吗 --------------------编程问答--------------------
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
不知道我说清楚没有。
--------------------编程问答-------------------- 0是new B()时调用父类的构造函数时输出的 null是调用a.print()时输出的
我想既然输出的不一样,应该输出的b值属于不用的实例对象一个是子类一个是父类
我感觉我这么想是错误的 但是我也只能想到这里了 我刚学java不久 --------------------编程问答--------------------
引用 3 楼 anshiny 的回复:
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
不知道我说清楚没有。

B的默认构造函数
public B() {
    super();
  }

调用完super()之后还会调用
private String b1 = null;
这条语句么 --------------------编程问答-------------------- 在执行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并不是同一个属性, --------------------编程问答--------------------
引用 6 楼 u010177022 的回复:
在执行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并不是同一个属性,

执行init();方法中的b1并非是执行a.print();时的b1,这两个b1不是同一个属性 这是什么意思 
那这个this.b1是什么呢 --------------------编程问答-------------------- 在我的程序中,去掉中的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了,
不知道这样的解释是否清楚, --------------------编程问答--------------------
引用 1 楼 lcf 的回复:
跟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();
  }
}

另外下次发帖记得用代码块高亮功能,不然看着很累


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

其他的楼上解释过了。。
--------------------编程问答-------------------- dbug走一下,看看怎么执行的。。 --------------------编程问答--------------------  A a = new B(); 
 会调用父类的构造方法,因为父类构造方法中调用了init方法,但是子类复写了init方法所以调用了子类的init方法。子类init中调用print方法也是调用的子类中的。。b1在子类的init方法中被赋值为0.所以会输出0.。
 在执行完父类构造函数的时候会执行到 private String b1=null; 所以此时b1=null了。
  a.print();
 执行依然是子类复写了的print方法。。所以这个地方就输出null咯。 --------------------编程问答-------------------- 除 --------------------编程问答-------------------- debug  虫子很强大 --------------------编程问答-------------------- 各位楼友说的很清楚了,楼主把他们的整理下,知识是慢慢积累的。我最近培训完java,我们可以交流下 --------------------编程问答-------------------- 继承情况下类的初始化顺序
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
--------------------编程问答--------------------
引用 15 楼 zyc13701469860 的回复:
继承情况下类的初始化顺序
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

也就是说一般类跟继承类的加载顺序不一样呗。
一般类是类变量在构造器之前初始化,继承类是先调用父类的构造器,然后是子类构造器,最后才是子类的成员变量初始化? --------------------编程问答-------------------- b1=0是在对象a构造的过程中赋值的  这个时候对象a其实还没有生成  b1有点像构造方法中的内部参数

因此等对象a生成后再去调用b1显示null --------------------编程问答-------------------- 父类指向子类对象 --------------------编程问答--------------------
引用 5 楼 qiulongjiemajianyun 的回复:
Quote: 引用 3 楼 anshiny 的回复:

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
不知道我说清楚没有。

B的默认构造函数
public B() {
    super();
  }

调用完super()之后还会调用
private String b1 = null;
这条语句么


自己 debug下! --------------------编程问答-------------------- --------------------编程问答-------------------- 很清楚了……我跟LZ的疑惑差不多,第一个0能明白,但是对前后两个b1不是同一个还是没理解透彻……学习了! --------------------编程问答-------------------- 用子类对象赋值个父类对象则该对象为上转型,上转型对象的特点是只可以调用从父类继承的变量或者方法还有在子类中被隐藏的变量(即变量名与父类的一样)和重写的方法。 --------------------编程问答-------------------- 除
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,