CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Java >  J2SE / 基础类

多态(真的搞不明白!)

楼主leqixb(清然)2005-04-04 17:30:14 在 Java / J2SE / 基础类 提问

abstract   class   Hello{  
          abstract   void   print();  
          Hello(){  
                  print();          
          }  
  }  
  class   Hi   extends   Hello{  
          int   i   =   5;  
          void   print(){  
                    System.out.println("Hi.i="+i);        
          }  
  }  
  public   class   Test{  
          public   static   void   main(String[]   args){  
                    Hi   hi   =   new   Hi();  
                    hi.print();        
          }          
  }  
  //结果:Hi.i=0                         Hi.i=5  
  Hello中是怎么调用Hi中的print()的?想不明白? 问题点数:20、回复次数:23Top

1 楼steedhorse(晨星)回复于 2005-04-04 17:36:57 得分 5

你要研究语言的底层实现么?  
  还有,你的程序根本没有从Hello类型上调用High。Top

2 楼zephyer(zephyr)回复于 2005-04-04 17:39:40 得分 3

搞不明白就记住结论好了:使用基类句柄调用方法,会调用实际引用的对象的方法  
  学习java也不必要把这些实现细节搞清楚  
  也没有几本java的书讲解了这些实现细节,包括Thinking   in   java  
  java注重的是思想  
   
  真要想搞明白多态的实现细节,看看thinking   in   C++之类C++书籍的相关章节,会讲解的很详细,也需要知道很多的基本知识  
  Top

3 楼leqixb(清然)回复于 2005-04-04 17:39:58 得分 0

anyone   help   me?  
  我在重看thinking   in   java,可是还有n个问题不明白!Top

4 楼milkbottle(奶瓶->好好学习,天天向上)回复于 2005-04-04 17:45:04 得分 1

因为   Hello   中的   print()已经被复写了,所以在这个过程中,可见的只有   Hi.print()  
   
  Hi.i=0             //   调用父类构造函数,   此时   Hi.i   还未被赋值,   只是被初始化为0  
  Hi.i=5             //   已经被赋值,   所以是5    
   
  Top

5 楼kingfish(工作很忙,很少来csdn...)回复于 2005-04-04 17:49:44 得分 5

先父类构造-再子类构造  
   
  i还没初始化,只是缺省值。Top

6 楼leqixb(清然)回复于 2005-04-04 17:56:55 得分 0

我是不明白在调用父类的构造函数时为什么会调用子类中的方法,难道真如milkbottle说的可见的只有   Hi.print()?忘继续指点!Top

7 楼ysbcg(Hummer)回复于 2005-04-04 18:04:08 得分 1

这个是动态绑定的作用,你在任何一个最终的对象中调用任何函数,他们的动态指向都是这个对象所对应的那个类所作的操作,这就是动态绑定。Top

8 楼menghuanlang(梦幻狼)回复于 2005-04-04 18:15:00 得分 0

我个人赞成  
  kingfish(八百里秦川@龙城异客)    
  的观点!Top

9 楼zephyer(zephyr)回复于 2005-04-04 18:18:09 得分 0

不是只有Hi.print()可见  
  而是编译器会根据具体的对象去决定调用哪个版本的方法  
  更具体的实现这里就不要讨论了,方法指针之类的概念java中都没有,仅仅学习java是无法进行详细的讨论的  
  Top

10 楼steedhorse(晨星)回复于 2005-04-04 18:32:17 得分 0

“我是不明白在调用父类的构造函数时为什么会调用子类中的方法。”  
   
  Java中任何方法的调用都是多态的,即使在构造函数中也如此。只要这个方法被重写,那么被调用的就永远是继承链中那个“lastest   overider”。Top

11 楼steedhorse(晨星)回复于 2005-04-04 18:39:17 得分 0

Java程序的执行,首先是源文件编译成二进制的类文件,一旦编译成类文件,就可以说所有的为实现多态所需要的准备工作都已经做好了。  
  比如你上面的例子,生成了class文件之后,其实不管是基类也好,派生类也好,所有调用print的地方并不是已经绑定到了具体的print方法的地址,而只是标记了一个入口,表示“这个地方要执行一个叫做print的函数。”(当然,实际上未必使用字符串标记),当运行时运行到那一步的时候,虚拟机就会根据继承链,来查找能在Hi类的对象上(因为hi实际是Hi类的对象)找到的print的最后一份实现,找到后,就执行它。  
   
  其实还有一个很明显的问题,Hello类自己也没有print的实现啊。Top

12 楼steedhorse(晨星)回复于 2005-04-04 18:41:56 得分 0

总之只需要记住:构造函数里照样可以多态,在这一点上跟一般函数没什么区别。  
  至于“对象还没构造好,怎么就多态了?”,原因是对象的内存已经分配好了,多态的条件已经完全具备了,构造函数不是负责分配内存的,内存由JVM分配,构造函数只是在JVM分配给对象的内存上做一些初始化的动作,从而初始化那块内存里的一些内容而已。Top

13 楼kingfish(工作很忙,很少来csdn...)回复于 2005-04-04 18:49:19 得分 0

楼上说得不错  
   
  不过有1句  
  //"其实还有一个很明显的问题,Hello类自己也没有print的实现啊。"  
  即使Hello类实现了print,这个例子中也不会调用  
   
  Hi   hi   =   new   Hi();  
                  =====  
                  这个是什么类型,那就会调用该类的print    
  Top

14 楼steedhorse(晨星)回复于 2005-04-04 19:02:52 得分 0

“即使Hello类实现了print,这个例子中也不会调用”  
  同意,俺只是补充一下,让楼主别忽略了这一点,在楼主的例子中,基类根本没有print的实现的。  
  Top

15 楼kingfish(工作很忙,很少来csdn...)回复于 2005-04-04 19:08:42 得分 0

同意+理解,呵呵  
   
  楼主想明白了就可以揭贴了。如果对底层实现很感兴趣,可以看看inside   JVM之类书或JVM   spec.Top

16 楼steedhorse(晨星)回复于 2005-04-04 19:18:34 得分 0

同意。:PTop

17 楼lxt322625(霞涛)回复于 2005-04-04 20:31:09 得分 2

Abstract   (抽象类)没有任何的功能   只是一个抽象的结构   所有的功能要求在子类中继承和实现   需要保证定义的方法必须被子类重载      
  抽象类不能创建一个实例化的对象   也不能声明一个抽象构造函数或抽象静态的方法     抽象类只能被继承而派生子类     所有继承抽象类而派生的子类必须实现父类的抽象方法Top

18 楼wangsheng1028(java菜)回复于 2005-04-04 23:23:04 得分 1

即使父类不是abstract也是一样的结果  
  那就是因为多态造成的。  
  他执行的是他的实际方法,子类的方法,但是在那时候i初始化还没被赋值。Top

19 楼bestdelphier(菜鸟升级中......)回复于 2005-04-05 00:32:42 得分 0

学习一下Top

20 楼slh002(呵呵)回复于 2005-04-05 00:47:00 得分 0

不太懂Top

21 楼ifmirror(镜子)回复于 2005-04-05 03:22:11 得分 1

若子类有覆盖父类的方法,那么指向子类对象的父类变量调用了该方法,被执行的会是子类的方法。Top

22 楼gtoliushan(k.m)回复于 2005-04-05 06:21:25 得分 1

abstract   class   A  
  {  
  abstract   void   print();  
   
  }  
  class   B   extends   A  
  {  
  void   print()  
  {  
  System.out.println("b");  
  }  
  public   static   void   main(String   args[])  
  {  
  A   a=new   B();  
  a.print();  
  }  
  }  
   
  看A类是一个抽象类。里面有一个抽象函数print,现在B类继承了A类。并且把A类的为被实现的print重写。也就是覆盖。现在看main()函数里面创建了一个A类的引用也就是a。他引用B类的无名对象。这时候a调用print函数。他输出的也就是B类的print。这就是多态。说白了就是a是基类的引用指向B类的对象。这时候a就可以调用B类的覆盖函数了。Top

23 楼leqixb(清然)回复于 2005-04-05 10:48:10 得分 0

谢谢各位,说很明白那是不可能的,还得在今后的实践中锻炼,结帖!Top

相关问题

  • 搞不明白?
  • 搞不明白
  • 不明白,真的不明白!!!!!!
  • 靠!DW4怎么会这样了。真是搞不明白!
  • 又搞不明白了!asp.net真是让我又爱又狠。
  • 真搞不明白,为什么用VC打开一个dsw时。。。。。。。。。。。。。。。
  • 搞不明白,很菜的问题,静态变量的赋值。请教了。
  • 我,我,我搞不明白!
  • 搞不明白,有关MDI
  • 我真的不明白?(急)

关键词

  • c++
  • 函数
  • 内存
  • 执行
  • jvm
  • 文件
  • 调用
  • 子类
  • 类
  • 抽象

得分解答快速导航

  • 帖主:leqixb
  • steedhorse
  • zephyer
  • milkbottle
  • kingfish
  • ysbcg
  • lxt322625
  • wangsheng1028
  • ifmirror
  • gtoliushan

相关链接

  • CSDN Java频道
  • Java类图书
  • Java类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo