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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 郝林杰 中级黑马   /  2014-4-4 23:01  /  889 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class Foo{
ppublic int a;
public Foo(){
a=3;
}

public void addFive(){
a+=5;
}
}

class Bar extends Foo{
public int a;
public Bar(){
a=8;
}
public void addFive(){
this.a+=5;
}
}

public class TestFoo{
public static void main(String [] args){
   Foo foo=new Bar();
   foo.addFive();
System.out.prinfln(foo.a);
}
}

输出的结果我认为是:13 可是正确的结果并不是,why?

4 个回复

倒序浏览
本帖最后由 残梦共飞雪 于 2014-4-5 10:15 编辑

原因是你子类Bar里面又定义了字段a,
Bar里的public int a;并未复写父类Foo的public int a;
也即构造时,有两个a,这两个a是不同的。主方法改成如下这般,可以直观显示:
public static void main(String[] args) {
                Foo foo = new Bar();
                System.out.println(foo.a);
                foo.addFive();
                System.out.println(foo.a);
                Bar bar = (Bar)foo;
                System.out.println(bar.a);
        }


结果为:
3
3
13


修改后的代码:
  1. class Foo {
  2.         public int a;

  3.         public Foo() {
  4.                 a = 3;
  5.         }

  6.         public void addFive() {
  7.                 a += 5;
  8.                 System.out.println("Foo a = " +a);
  9.         }

  10.         public int getA() {
  11.                 return a;
  12.         }
  13. }

  14. class Bar extends Foo {
  15.         public Bar() {
  16.                 a = 8;
  17.         }
  18.         @Override
  19.         public void addFive() {
  20.                 this.a += 5;
  21.                 System.out.println("Bar a = " +a);
  22.         }
  23. }

  24. public class TestFoo {
  25.         public static void main(String[] args) {
  26.                 Foo foo = new Bar();
  27.                 System.out.println(foo.a);
  28.                 foo.addFive();
  29.                 System.out.println(foo.a);
  30.         }
  31. }
复制代码

运行结果:8
Bar a = 13
13



评分

参与人数 1技术分 +1 收起 理由
菜小徐 + 1

查看全部评分

回复 使用道具 举报
首先,你那println写成ptinfln了,  你new Bar()时, 有条隐式的super(); 调用父类的构造函数,这是foo.a=3, 然后子类的a=8, 在复写父类的方法,调用子类的方法a+=5, 那么输出 bar a=13,  你foo.a则是调用是父类的a,, 所以成员变量不存在覆盖.      
回复 使用道具 举报
1.在多态中成员函数的特点:
        在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
        在运行时期:参阅对象所属的类中是否有调用的方法。
        简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。
2.在多态中,成员变量的特点:
        无论编译和运行,都参考左边(引用型变量所属的类)。
3.在多态中,静态成员函数的特点:
        无论编译和运行,都参考做左边。

按照你的意思代码改成这样你看看:
  1. class Foo{
  2.         public int a;
  3.         public Foo(){
  4.                 a=3;
  5.         }

  6.         public void addFive(){
  7.                 a+=5;
  8.         }
  9. }

  10. class Bar extends Foo{
  11.         public int a;
  12.         public Bar(){
  13.                 super.a=8;
  14.         }
  15.         public void addFive(){
  16.                 super.a+=5;
  17.         }
  18. }

  19. public class TestFoo{
  20. public static void main(String [] args){
  21.         Foo foo=new Bar();
  22.         foo.addFive();
  23.         System.out.println(foo.a);
  24. }
  25. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
菜小徐 + 1

查看全部评分

回复 使用道具 举报 1 0
成员变量编译运行都左边,知道吗,成员函数编译看左边运行看右边,希望对你有记忆
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马