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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 何仕映 中级黑马   /  2013-3-17 19:48  /  2167 人查看  /  11 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 何仕映 于 2013-3-17 21:08 编辑

毕老师在视频中讲到多态成员变量的特点是:无论编译和运行都看左边。
如果是这样那么下面这个程序打印的结果应该是1啊,为什么打印输出的结果是2呢?
  1. interface A
  2. {
  3.         int a = 1;
  4.         public abstract void printOut();
  5. }

  6. class B implements A
  7. {
  8.         int a = 2;
  9.         public void printOut()
  10.         {
  11.                 System.out.println(a);
  12.         }
  13. }
  14. class  DuoTaiDemo
  15. {
  16.         public static void main(String[] args)
  17.         {
  18.                 A b =new B();
  19.                 b.printOut();
  20.         }
  21. }
复制代码

11 个回复

倒序浏览
哥们,你看视频要看完全啊!
老师的总结是这样的

非静态成员函数   编译看左边,运行看右边

静态成员函数   编译看左边,运行看左边

非静态成员变量   编译看左边,运行看左边

静态成员变量   编译看左边,运行看左边

毕老师还举了一个很好的例子,毕老爷和毕老师!你把这个例子想明白了就可以啦!!
回复 使用道具 举报
同学 你的A抽象了  B复写了A的方法 而且主函数调用的是B的方法 B中a=2 所以 输出的是2
回复 使用道具 举报
各位大神,小弟神经短路了,还是不懂呢。
回复 使用道具 举报
你的这段代码并没有体现,多态中成员变量的特点,而是体现了多态中方法动态绑定的特点
你可以将测试代码 改下
  1. class  DuoTaiDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 A b =new B();
  6.                System.out.println(b.a);
  7.         }
  8. }
复制代码
这样输出结果才是你预想的结果
回复 使用道具 举报
首先你要明白 A b = new B()创建的是B类的一个对象,真正调用printOut的也是B类的这一个实例对象,所以他会调用B类中的printOut方法。B要输出a的值,他首先看一下自己有没有,如果有的话就用自己的,如果没有就用自己的父类或者自己实现的接口上的(如果有的话),
回复 使用道具 举报
成员变量是看左边,但是你调用的是方法啊,你调用b.a,看看是多少?
回复 使用道具 举报
interface A
{
        int a = 1;
        public abstract void printOut();
}

class B implements A
{
        int a = 2;
        public void printOut()
        {
                System.out.println(a);
        }
}
class  DuoTaiDemo
{
        public static void main(String[] args)
        {
                A b =new B();
                b.printOut();//这里调用了b的方法,而b里面有该方法,重写了父类的方法,先看子类里面有没有,没有的话再到父类里面找
        }
}
给你我之前写过的思路
孔子爹:教书("JavaSE"),40//孔子爹年龄40,教javaSE
孔子:教书("论语"),玩游戏(),20//孔子年龄20,教论语
//有人找孔子爹去教书,结果只有孔子在家,孔子化妆成爹去教
孔子爹 k爹 = new 孔子();  //向上转型 化妆,装爹。
k爹.教书(); //方法重写,孔子只会教论语,所以是论语
sop(k爹.age); //而年龄是化妆出来的,就是父类的年龄是40
//下课了
孔子 k = (孔子)k爹; //向下转型 去妆,还原本身
                孔子 k = new 孔子();
                k.教书(); //教书还是只能教论语
                sop(k.age); //卸过妆之后年龄就是20
                k.玩游戏();可以使用自己独有的方法
看懂这个例子以后遇到什么情况都往这个方向走就可以了
回复 使用道具 举报
interface A

{

        int a = 1;

        public abstract void printOut();

}



class B implements A

{

        int a = 2;

        public void printOut()

        {

                System.out.println(a);

        }

}

class  DuoTaiDemo

{

        public static void main(String[] args)

        {

                A b =new B();

                b.printOut();

        }

}
你调用的是成员方法,应该执行子类重写的方法。打印:2是对的。
在多态中成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。


在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。


在多态中,静态成员函数的特点:
无论编译和运行,都参考做左边。
回复 使用道具 举报
崔自成 发表于 2013-3-17 20:20
你的这段代码并没有体现,多态中成员变量的特点,而是体现了多态中方法动态绑定的特点
你可以将测试代码 改 ...

谢谢你,哥们。神经短路了,就你的回答,简洁,明了。
回复 使用道具 举报
我知道你的迷惑在哪里了,我也遇到这样的问题!


首先【声明】
毕老师讲的我们都知道:
一、在多态中【<非静态>成员函数】的特点:
    在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,否则失败。
    在运行时期:参阅对象所属的类中是否有调用的方法。

    简单总结就是:成员函数在多态调用时,编译看左边,运行看右边。

二、在多态中,【成员变量】的特点:
    无论编译和运行,都参考左边(引用变量所属的类)。
三、在多态中,【静态成员函数】的特点:
    无论编译和运行,都参考左边。


但是【问题】在于,我们认为(就拿楼主的代码举例):
一、类B实现了接口A,并且实现了方法printOut,当执行 A b =new B();    b.printOut(); 的时候,
    肯定是执行的子类中的printOut方法,这也符合【声明】中的第一点,
    然而我们认为是printOut方法中访问打印了变量a,结合【声明】中第二点,认为这时候应该是打印父类中的a,即结果应该为1;
二、【问题在哪呢?】,仔细想想是我们理解错了!
    因为【声明】中第二点的确切意思是,直接通过对象.成员变量如打印b.a的时候,才会符合【声明】中第二点;
    另外【声明】中第二点存在的原因是因为b.a无法确认是哪个a,所以才有了这一点;
    但是楼主的代码中运行的是成员函数,所以按照声明 中的第一点,执行子类中的方法,即使方法中访问了成员变量,但因为变量名前省略了关键字this,所以能够确定要执行子类中的a,即2;总之执行子类中的方法时要严格执行就对了。


希望上面的回答,对楼主有帮助。
   
   
回复 使用道具 举报
本帖最后由 黑马-王鹏 于 2013-3-17 21:33 编辑

在接口中,子类实现父类,要复写父类方法,b.printOut();这个语句可以看出父类的引用要调用printOut()这个方法,必须是子类的方法,所以就是2,代码并没有体现多态
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马