A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© up_ 中级黑马   /  2012-10-24 13:38  /  2019 人查看  /  4 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

class A{
String str="A";//加载到这里不是指向了“A”才对吗?
A(){
init();
}
public void init(){
System.out.println(str);
}
}
class B extends A{
String str="B";
B(){
super();
}
public void init(){
System.out.println(str);
}
}

  public static void main(String[] args){
  A b=new B();
  System.out.println(b.str);
  }

运行结果为null,这段代码的加载过程是怎样的?详求?

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

4 个回复

倒序浏览
程序从main方法进入,因为new B()所有调用B的构造方法,B的构造方法又是继承A 的,所有调用A的构造方法,A的构造方法调用init()会打印出str=A;接着main继续,打印b.init()。你那直接b.str应该不行吧

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

回复 使用道具 举报
这个程序主要用到了java多态的特点,当然还包括了方法的覆盖等。在运行时环境中,通过引用类型访问所引用对象的方法和属性时:实例方法与引用变量实际的对象的方法绑定,这种属于动态绑定。成员变量和静态方法属于静态绑定。因此,在实例化B对象时,需要先实例化A,A类构造方法会调用init()方法,由于我们在B类中覆盖了A类的init()方法,根据动态绑定原则,此时不会调用A类的init(),而是调用B类的init()方法。而打印b.str时,采用的静态绑定原则,会输入当前对象的成员变量值

评分

参与人数 1技术分 +1 收起 理由
张榆 + 1

查看全部评分

回复 使用道具 举报
从new B()开始,然后通过super()到类A的构造方法开始(尚未执行A()构造方法的代码),然后接着初始化A类的str,然后执行A构造方法里面的init(),这个init()前面隐含的this对象(打印this.getClass()可以知道这个this是B类的实例---个人觉着可以这样解释因为A的构造方法在这里是被B类的构造方法调用来构造B实例的,从B的角度看,A的构造方法其实就是B()构造方法的一部分,所以此时的A构造方法里this应该是B类型的),在这里B类型的实例当然调用的自己的init方法,要注意执行到A构造方法的init()时(真正调用的是B类的init方法),B类的str变量还没有初始化,所以这里的打印是null;
java的属性不支持多态,所以b.str打印的仍会是“A”,希望有用。
回复 使用道具 举报
为什么会出现null, A b = new B(); 多态中成员函数的运行看右边,变量看左边,静态成员看左边。
首先运行B(),那么会到,父类中去看看父类是怎么初始化的,会运行A(){ intit();},因为多态,成员函数 init(),运行的是 子类B中的init,这时候输出的也会是
子类B中的str,因为构造函数先加载的,而Str还没有加载,默认初始化为 null,因此输出的是B中的init();为null。
main函数中b.str,多态成员变量看左边,输出的是A中的str。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马