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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 章闽 中级黑马   /  2012-10-22 11:20  /  1369 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文


class A
{
public void f()
{
System.out.printf("AAAA\n");
}
}

class B extends A
{
public void f()
{
System.out.printf("BBBB\n");
}
}

public class TestPoly
{
public static void main(String[] args)
{
A aa = new A();
B bb = new B();

aa.f();
bb.f();

aa = bb;
aa.f();
}
}

根据Java多态的一个定义:通过父类引用只能访问子类对象从父类继承过来的成员
类B中重写的了A中的方法f();这个应该是B类中的一个方法了 但是aa = bb;aa.f();输出的结果是bb.f();中的结果啊 这里不是跟上面有矛盾吗?

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1 很给力!

查看全部评分

6 个回复

倒序浏览
你是吧aa提升了,是他具备了B类的功能
回复 使用道具 举报
这个不矛盾,aa = bb;相当于A aa= new B();向上转型了。
因为你的子类和父类中都有f()方法,对于非静态方法:在编译时参考引用型变量所属类中(就是父类中)是否具有调用的f()方法,有,编译通过。
但是在运行时,参考的是对像所属类中是否具有调用的方法,就是子类中了,有的话运行子类的,子类中没有就往父类中寻找,有运行父类的,父类也没有就运行失败。

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1 很给力!

查看全部评分

回复 使用道具 举报
通过父类引用只能访问子类对象从父类继承过来的成员--- 应该这样理解吧:子类对象赋给父类引用时,父类引用只能访问子类对象从父类继承过来的成员(包括在子类中已重写的)。记住一点,继承是类之间的关系,重写是方法之间的关系。你的例子我少加了点东西,就好理解了;
=================================================================
  1. class A {
  2.         public void f() {        //它其实没有被继承过去,因为子类直接重写了它
  3.                 System.out.printf("AAAA\n");
  4.         }
  5.         public void fun(){        //它会被子类整个继承,并且子类没有重写它
  6.                 System.out.println("fun run...");
  7.         }
  8. }

  9. class B extends A {
  10.         public void f() {        //重写过的f方法
  11.                 System.out.printf("BBBB\n");
  12.         }
  13.         public void fun1(){        //子类特有的方法
  14.                 System.out.println("我能编译,不能运行");
  15.         }
  16. }

  17. public class TestPoly {
  18.         public static void main(String[] args) {
  19.                 A bb = new B();        //子类对象给父类引用
  20.                 bb.f();        //多态就是编译时方法看父类有没有,运行时看实际对象类有没有,这里运行的是子类的f()
  21.                 bb.fun();        //这里运行的也是子类的fun(),只不过是直接从父类中继承过来的罢了
  22.                 bb.fun1();        //能编译不能运行,因为父类中没有fun1

  23.                 A aa = bb;        //这个就是换个手,a类引用给a类引用(运行时仍参照b对象)
  24.                 aa.f();
  25.         }
  26. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1 很给力!

查看全部评分

回复 使用道具 举报
aa.f() 相当于 new A().f()  ,调用A中的f()
bb.f() 相当于 new B().f()  ,调用B中的f()
aa=bb 之后,
aa.f() 相当于 bb.f()  也就是 new B().f()
所以调用的还是B中的f()

评分

参与人数 1技术分 +1 收起 理由
韩军博 + 1 很给力!

查看全部评分

回复 使用道具 举报
首先这两者是不矛盾的。
代码中:

A aa = new A();  //创建父类对象
B bb = new B();  //创建子类对象

aa = bb;  只是传递的是对象引用,并不会进行类型自动提升。
只是两者会指向在堆内存中的相同地址。
所以对象 aa.f();调用父类的方法, bb.f(); 调用子类的方法。
虽然子类复写父类的方法,但是子类对象调用本类方法。

而  A aa = bb;
bb会自动提升为父类 A; 则  aa.f(); 输出的结果是aa.f();而不是bb.f();

回复 使用道具 举报
本帖最后由 NESUN 于 2012-10-22 16:19 编辑

    这里的aa = bb发生了向上的类型转换,其实就是bb对象换了一个马甲而已,看着是aa,最后运算的时候还得自己来。所以就不难解释,为什么会出现调用的是aa.f(),结果却是调用了bb.f()方法。
  还有一点就是方法重写之后是自己的方法吧?应该不是继承了吧?我是这么觉得的,你怎么看呢!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马