黑马程序员技术交流社区

标题: 问一个和多态相关的问题。 [打印本页]

作者: 黄小橙    时间: 2014-8-26 21:01
标题: 问一个和多态相关的问题。
本帖最后由 黄小橙 于 2014-8-27 09:53 编辑

视频里毕老师讲过
在多态中成员变量的特点:只看引用变量所属的类。即无论编译和运行,都参考左边(引用型变量所属的类)。
--------------------------------------------------------------------------------------------------------------------
那为什么下面代码的答案不是B C 2 而是B C 5呢?
按照我的理解是:Super类里面的i变量通过 构造函数的初始化后就变成2了。然后Demo类里面的i变量通过构造函数初始化后就变成了5,
而d.i调用的i是Super类里面的,那应该是i=2啊。。。求大神们解答一下。
-------------------------------------------------------------------------------------------
class Super
{
    int i = 0;
    public Super()
    {
        System.out.println("B");
        i+=2;
    }
}

class Demo extends Super
{
    public Demo(String a)
    {
        System.out.println("c");
        i = 5;
    }
    public static void main(String[] args)
    {
        int i = 4;
        Super d = new Demo("A");
        System.out.println(d.i);
    }
}


作者: 黄小橙    时间: 2014-8-26 21:14
{:3_52:}有哥们帮忙解答一下么。。。
作者: noiary    时间: 2014-8-26 21:28
好混乱,我整理下~
作者: noiary    时间: 2014-8-26 21:40
本帖最后由 noiary 于 2014-8-26 21:49 编辑

                                       1
作者: 舍我其谁    时间: 2014-8-26 21:41
noiary 发表于 2014-8-26 21:28
好混乱,我整理下~

编译看左边,运行看右边,
作者: 黄小橙    时间: 2014-8-26 21:46
noiary 发表于 2014-8-26 21:40
想画图来着,然后发现...我不会画...

我想 , 顺序应该是这样的:

你的意思是Demo类构造函数中操作的i变量和父类构造函数中操作的i变量是同一个i吗
作者: 黄小橙    时间: 2014-8-26 21:48
本帖最后由 黄小橙 于 2014-8-27 09:52 编辑
舍我其谁 发表于 2014-8-26 21:41
编译看左边,运行看右边,

编译看左边,运行看右边。是成员函数在多态调用时的吧。 d.i是调用变量,变量是无论编译和运行都看引用型变量所属的类。
作者: noiary    时间: 2014-8-26 21:50
黄小橙 发表于 2014-8-26 21:46
你的意思是Demo类构造函数中操作的i变量和父类构造函数中操作的i变量是同一个i吗 ...

你这么疑问我也不确定啦 哈哈  

这是个值得探讨的问题... 我们可以做实验证明一下
作者: 舍我其谁    时间: 2014-8-26 21:50
黄小橙 发表于 2014-8-26 21:48
编译看左边,运行看右边。是成员函数在多态调用时的吧。 d.i是调用静态,静态是无论编译和运行都看引用型 ...

你是在静态函数里调用没错,但是你是用对象调用的,
作者: noiary    时间: 2014-8-26 21:59
黄小橙 发表于 2014-8-26 21:48
编译看左边,运行看右边。是成员函数在多态调用时的吧。 d.i是调用静态,静态是无论编译和运行都看引用型 ...
  1. class Super
  2. {
  3.     int i = 0;
  4.     public Super()
  5.     {
  6.         //System.out.println("B");
  7.         i+=2;
  8.     }
  9. }

  10. class Demo extends Super
  11. {
  12.     public Demo(String a)
  13.     {
  14.         //System.out.println("c");
  15.         i = 5;
  16.     }
  17.     public static void main(String[] args)
  18.     {
  19.         int i = 4;
  20.         Super d = new Demo("A");
  21.        // System.out.println(d.i);
  22.                
  23.                 Super d2 = new Demo("B");
  24.                 Super d3 = new Super();
  25.                 //System.out.println(d2.i);
  26.                
  27.                 d.i++;
  28.                 System.out.println(d.i);
  29.                 System.out.println(d2.i);
  30.                 System.out.println(d3.i);
  31.     }
复制代码


打印结果是
6
5
2
作者: noiary    时间: 2014-8-26 22:03
我想 ,  Demo创建对象的时候, 就把i的值创建成了5, 存放到了堆内存.

d.i调用的就是此堆内存当中的i.而不是父类Super中的变量i.
作者: 黄小橙    时间: 2014-8-26 22:32
noiary 发表于 2014-8-26 22:03
我想 ,  Demo创建对象的时候, 就把i的值创建成了5, 存放到了堆内存.

d.i调用的就是此堆内存当中的i.而不 ...

我将函数改成:
  1. class Super
  2. {
  3.         int i = 0;
  4.         public Super()
  5.         {
  6.                 i+=2;
  7.         }
  8. }

  9. class Demo extends Super
  10. {
  11.          
  12.        
  13.         public Demo(String a)
  14.         {
  15.                 System.out.println("i="+i);
  16.                 i += 5;
  17.         }
  18.         public static void main(String[] args)
  19.         {
  20.                 int i = 4;
  21.                 Super d = new Demo("A");
  22.       
  23.                 System.out.println(d.i);
  24.                
  25.         }
  26. }
复制代码


结果是i=2    7
所以Demo构造函数对i的操作的确是用父类构造函数的结果来操作的。
作者: noiary    时间: 2014-8-27 08:19
黄小橙 发表于 2014-8-26 22:32
我将函数改成:

是的, 父类Super的成员变量i在栈内存,赋值为0;
创建子类对象后,子类对象运行Super构造函数,此时i被赋值为2;
紧接着输出子类构造函数Demo()中的 System.out.println("i="+i) 也就是 i = 2;
下面i又被赋值+5也就是2+5=7,我想这个i应该是在堆内存被创建的对象 new Demo() 当中,所以调用d.i 是7.

我想这时栈内存中的i应该还是7吧?  一会验证一下.

作者: noiary    时间: 2014-8-27 09:02
本帖最后由 noiary 于 2014-8-27 09:09 编辑
黄小橙 发表于 2014-8-26 22:32
我将函数改成:
  1. class Super
  2. {
  3.         int i = 0;
  4.         public Super()
  5.         {
  6.                 i+=2;
  7.         }
  8.                
  9.                 public int getI() {
  10.                
  11.                         return i;
  12.                 }
  13. }

  14. class Demo extends Super
  15. {
  16.          
  17.         
  18.         public Demo(String a)
  19.         {
  20.                 System.out.println("i="+i);
  21.                 i += 5;
  22.         }
  23.                
  24.                

  25.                
  26.         public static void main(String[] args)
  27.         {
  28.                 int i = 4;
  29.                 Super d = new Demo("A");
  30.                                 
  31.                 System.out.println(d.i);
  32.                                 d.i++;
  33.                 System.out.println("super.i= " + d.getI());
  34.         }
  35. }
复制代码


结果是
i=2
7
super.i= 8

d.i 变化  super.i也会变化....
回头要重新看看老毕的视频了..

作者: 黄小橙    时间: 2014-8-27 09:42
noiary 发表于 2014-8-27 09:02
结果是
i=2
7

嗯,我昨天弄明白了
从结果来看确实是符合多态成员变量中的特点:看引用变量所属的类。
其实就是Demo构造函数中的i+=5;中的i省略了super
  1. public Demo(String a)
  2.         {
  3.                 System.out.println("i="+i);
  4.                 super.i += 5;
  5.         }
复制代码


所以Demo构造函数对i的操作的确是用父类构造函数的结果来操作的。
d.i调用的是引用变量所属类的变量,所以值是7.

辛苦哥们了,加个好友,此贴终结。

作者: 文盲庄稼汉    时间: 2014-8-27 09:45
围观.路过
作者: 戏言丶    时间: 2014-8-27 09:45
我是过来学习的:lol
作者: LFW    时间: 2014-8-27 10:05
class 动物{}   class猫 extends动物{   main{ 动物 d =new 猫(“鱼”) ;  sop(动物 d 吃什么?)   }}  
作者: abc83983682    时间: 2014-8-27 10:39
貌似楼主没理清关系!望再好好想想!
作者: noiary    时间: 2014-8-27 15:22
我想我也明白了.

创建对象Super d = new Demo();  先运行子类构造函数,子类构造函数内先运行super() 父类构造函数,  所以i被赋值为2,(此i在子类中,而非父类)
这时父类中无论是构造函数Super()  还是i , 应该没有任何动作,  有的只是在子类中的 i = 0;    i += 2;    i += 5 ; 所以d.i结果才会为7.



不知道我这样理解对不对,我想是对的..{:3_67:}





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2