黑马程序员技术交流社区

标题: 关于向下转型的问题 [打印本页]

作者: ankje    时间: 2015-3-7 21:46
标题: 关于向下转型的问题
    先说说我的目的,就是利用已经被向上转型的对象去访问子类中特有的函数,于是通过代码中(===正常部分===)实现了。但我现在想用另外一种办法去达到相同的目的,于是就有了代码中(===试验部分===)。那么我想问问大家,为什么代码中(===试验部分===)会编译失败呢??!!!
  1. class Fu{
  2.         void show(){
  3.                 System.out.println("父类");
  4.         }
  5. }

  6. class Zi extends Fu{       
  7.         void show(){
  8.                 System.out.println("子类");
  9.         }       
  10.         void fun(){
  11.                 System.out.println("子类特有的函数");
  12.         }
  13. }

  14. class Test{       
  15.         public static void main(String[] args){
  16.                
  17.     //================正常部分开始=====================
  18.        
  19.                 Fu f = new Zi(); //向上转型       
  20.                
  21.                 Zi a = new Zi();//创建子类对象
  22.                 a.fun();//调用子类特有函数
  23.                
  24.                 Zi b = (Zi)f;//向下转型
  25.                 b.fun();//调用子类特有函数
  26.                
  27.     //================正常部分结束=====================
  28.                
  29.                
  30.         //================试验部分开始=====================
  31.        
  32.                 f = (Zi)f;//尝试以这种方式向下转型
  33.                 if(f instanceof Zi){
  34.                         System.out.println("f现在是子类");//这里成功打印,说明 f = (Zi)f 这句话应该没什么问题吧
  35.                 }
  36.                 f.fun();//这里编译错误,提示 父类中没有fun()的这个函数
  37.                
  38.         //================试验部分结束=====================
  39.         }       
  40. }
复制代码






作者: z47057554    时间: 2015-3-8 03:48
本帖最后由 z47057554 于 2015-3-8 04:05 编辑

试验部分的问题
你的f是由父类定义的指针,f=(Zi)f;相当于
fu f2=(Zi)f;//这跟 fu f=new Zi();是一个道理
f2.fun();
(Zi)f 是向下转型,但转完后你又把它赋给了父类指针,这又是一次向上转型,做的是无用功,结果还是只能调用父类的方法
至于你打印的那句话是,哪怕你把在前面的f=(Zi)f;去掉,它也不会变化,这里不是看前面的指针是谁,而是看指针指向的对象是谁。
你即便这样做
Object obj=(Zi)f;
然后,再输出判断obj是否Zi类类型,输出结果也是真
这样来回赋值,它改变的只是指向堆内存中对象的栈内存中的值,并不会改变堆内存中的对象,它该是什么类还是什么类,只不过指向他的指针变化了



作者: 硫氢化铁    时间: 2015-3-8 07:49
子类可以实现到父类的类型转换,这叫向上转型,但是父类到子类的直接转换是不容许的,因为子类是父类的一个超集,他必须具备父类中包含的所有成员方法,并可能比父类拥有更多的成员方法。
作者: 白春秋    时间: 2015-3-8 08:19
这属于多态调用成员函数的问题特点是:编译时看引用性变量所在类中有没有被调用的函数,运行时看实例对象所在类中有没有被调用的函数,即调非静态成员函数时,编译看等号左边,运行看右边。 f.fun()这句话的理解是:调用成员函数的是new Zi()实例对象,而不是引用型变量f(仅仅是一个对象实体的引用地址值),非静态成员函数调用所依赖的是调用它的对象实体,而不是对象实体的引用
和多态时调用成员变量是有区别的
作者: lwj123    时间: 2015-3-8 14:55
Fu f = new Zi(); //向上转型      
f = (Zi)f;//尝试以这种方式向下转型
(Zi)f:表示的是将指向Zi对象f强转为Zi对象
f = (Zi)f:表示的是Zi对象向上转型为Fu
f.fun():这里的f代表的是Fu的对象,fun是父类Fu中不具备的,所以就无法编译通过




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