黑马程序员技术交流社区

标题: 这是 向上转型 还是 向下转型? [打印本页]

作者: aohn1117    时间: 2016-2-29 22:34
标题: 这是 向上转型 还是 向下转型?

interface D {}


class C {}


class B extends C {}


public class A extends B implements D{

     public static void main(String[] args) throws Exception {

            C c = new A();

            D d = (D)c;

    }

}

请问D和C什么关系?   (D)c这个操作是向上转型?还是向下转型?

什么是转型?? 转型是怎么实现的?   

short a =0 ;              

int i = a;                     

a = (short)i;


A a = new A();

C c = a;

A a1 = (A)c;

以上两者有什么区别?




作者: bestcaptain    时间: 2016-3-4 17:00
D和C的关系:只有A实现的D,所以
C c = new A();D d = (D)c;
应该等同于D c=(D)(new A());这里是向上转型;
转型分为向上转型和向下转型
向上转型是父类引用指向子类对象,格式为 父 f=new 子();
打个比方,当需要讲一系列子类对象作为参数传递给一个函数的时候,就可以只写一个方法,而参数仅仅是父类对象,这样只需要创建其中一个子类对象并加以父类引用即可,讲父类的引用作为参数传递就可以实现具体的子类对象作为参数传递的效果,也就是说讲"写多个方法"转变为"只写一个方法而随时创建需要的指向该子类对象的父类引用"即可
这样无论是在代码的简洁还是在开发中的后期 维护方面都有很大的优势.向上转型通常是程序员自己编写程序的时候用到.
向下转型则类似于强转,是将被父类引用指向的对象改为自己类引用对象,格式为: 子 z=(子)f;(其中f为指被父类引用指向的子类实例)
还是举个参数传递的例子,这里用Object来说明,比如一个方法中本来实现的功能是对传入的字符串进行操作,但是在写方法的时候却可以吧参数类型写为Object,即你传入什么样的参数都可以,暂时不对参数进行过滤,但是在方法中却需要对传入的参数进行判断,通常用 obj instanceof String来实现,如果obj确实是String类的一个实例,那么才能向下转型,并调用子类对象的特有方法.当不判断的时候则可以选择抛出异常,如果传入String的实例同样可以继续操作.向下转型的原因是是放宽了参数传递的范围,通常是面向客户的时候采用,而将麻烦留给自己,调用子类对象的特有方法.

short a =0 ;              
int i = a;                     
a = (short)i;


A a = new A();
C c = a;
A a1 = (A)c;
区别在于
基本类型的转换是以存储该数据的字节容量为依据的,int i=a时会吧两个字节的a用一个四字节的内存存储,并在前面两个字节的长度补上0,是内存转换的关系.而int转short时则是讲int数强行压到short的内存中,原则是不损失精度.
对象的类型转换是已是否为父子类或者是否是接口和实现类的关系为依据的.C c=a;时把一个父类引用指向了子类对象,是指向的关系,我们可以把这只小鸟说成是一只小动物,却不可以吧一个short型字符说成是这个int型字符,而A a1 = (A)c;则是把A类型实例的父类引用转换为该类引用,我们可以吧一只是小鸟的小动物说成小鸟,却不可以吧一个
比short类型字节数长的相等的int型字符说成是short型字符.
区别有种种说法,重在理解,以上内容纯手打,还望楼主不吝赏币!





作者: 不落羽    时间: 2016-3-4 23:15
一般情况下:
   
     带 ( ) 的为向下转型 , 可以通过强制类型转换的原理来理解记忆 ;
     double 类型比 int 类型占据的空间要大 , 因此例如:  int x=(int) 3.6;

详情解释:
     
转型是在继承的基础上而言的,继承是面向对象语言中,代码复用的一种机制,通过继承,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展。

向上转型:子类引用的对象转换为父类类型称为向上转型。通俗地说就是是将子类对象转为父类对象。此处父类对象可以是接口

向下转型:父类引用的对象转换为子类类型称为向下转型。

前者是一个向上转型,Animal dog 引用指向new Dog();子类对象当成父类对象,只能调用父类的成员,如果子类重写了父类的方法就根据这个引用指向调用子类重写的这个方法(这个方法就是覆盖override)。这个调用过程就称为“动态绑定”。

转型需要注意的问题:

向上转型时,父类指向子类引用对象会遗失除与父类对象共有的其他方法,也就是在转型过程中,子类的新有的方法都会遗失掉,在编译时,系统会提供找不到方法的错误。实例如下:

public class Animal {

         public void eat(){

                   System.out.println("animal eatting...");

         }

}

class Bird extends Animal{

         public void eat(){

                   System.out.println("bird eatting...");

         }

         public void fly(){

                   System.out.println("bird flying...");

         }

}

class Main{      

         public static void main(String[] args) {

                   Animal b=new Bird(); //向上转型

                   b.eat();

         b.fly();  //此处提示在Animal中没有定义fly方法。



在向下转型过程中,分为两种情况:

情况一:如果父类引用的对象如果引用的是指向的子类对象,那么在向下转型的过程中是安全的。也就是编译是不会出错误的。

情况二:如果父类引用的对象是父类本身,那么在向下转型的过程中是不安全的,编译不会出错,但是运行时会出现java.lang.ClassCastException错误。它可以使用instanceof来避免出错此类错误。实例如下:

public class Girl {

         public void smile(){

                   System.out.println("girl smile()...");

         }

}

class MMGirl extends Girl{

                   @Override

         public void smile() {

                                     System.out.println("MMirl smile sounds sweet...");

         }

         public void c(){

                   System.out.println("MMirl c()...");

         }

}

class main{

                   public static void main(String[] args) {

                   Girl g1=new MMGirl(); //向上转型

                   g1.smile();

                   MMGirl mmg=(MMGirl)g1;    //向下转型,编译和运行皆不会出错

                   mmg.smile();

                   mmg.c();

                   Girl g2=new Girl();

           //MMGirl mmg1=(MMGirl)g2; //不安全的向下转型,编译无错但会运行会出错

           //mmg1.smile();

           //mmg1.c();

                   if(g2 instanceof MMGirl){

                            MMGirl mmg1=(MMGirl)g2;

                            mmg1.smile();

                            mmg1.c();

                   }

         }

总结:

1、父类引用可以指向子类对象,子类引用不能指向父类对象。

2、把子类对象直接赋给父类引用叫upcasting向上转型,向上转型不用强制转型。

   如Father father = new Son();

3、把指向子类对象的父类引用赋给子类引用叫向下转型(downcasting),要强制转型。

   如father就是一个指向子类对象的父类引用,把father赋给子类引用son 即Son son =(Son)father;

   其中father前面的(Son)必须添加,进行强制转换。

4、upcasting 会丢失子类特有的方法,但是子类overriding 父类的方法,子类方法有效

5、向上转型的作用,减少重复代码,父类为参数,调有时用子类作为参数,就是利用了向上转型。这样使代码变得简洁。体现了JAVA的抽象编程思想。
作者: lwy_ofb    时间: 2016-3-4 23:46
C继承了D,然后(D)c这个操作应该是向下转型吧
作者: 就是我    时间: 2016-3-5 18:05
D是接口,C是父父类,B是C的子类,A继承B实现D;所以D跟C没关系;(D)c应该算向上转型;什么是转型,转型怎么实现(度娘);两者区别,一个是基本数据类型转型,一个是引用数据类型转型,1可能会产生意想不到的错误,2则完全合乎道理
作者: tsldxszd    时间: 2016-3-6 17:40
本帖最后由 tsldxszd 于 2016-3-6 19:21 编辑

d和c没关系,这程序虽然不报错,可 你 的D d也无法访问继承类的特有方法

作者: 执剑人    时间: 2016-3-6 18:15
c的剪接子类实现了D,向下转型,把C类型强转为D类型。1属于向上转型,不需要创建对象!2,属于向下转型,需要创建对象!
作者: tsldxszd    时间: 2016-3-6 18:18
tsldxszd 发表于 2016-3-6 17:40
d和c没关系,这程序报错,应该是castexception,转型异常

我的答案错了,无视
作者: tsldxszd    时间: 2016-3-6 18:23
应该是没关系,没有转型存在,你的code应该是
c c=new a();d d =new a();你的d只能调用a实现了方法,而不能调用a继承自c,b的方法
作者: sholldoll    时间: 2016-3-8 21:47
1.请问D和C什么关系?
类和接口的关系只有实现关系,显然这里不是C实现D,所以C和D并没有直接关系。C是A父类的父类,D是A实现的接口。
2.(D)c这个操作是向上转型?还是向下转型?
向上转型。C c = new A();创建一个A对象用C类的的c接收,
               D d = (D)c;这里的c就是new A();所以D d =(D)(new A());    //这里的new A()不是创建了新的对象,而是用了c创建出来的 new A(); 最终d和c指向的是同一地址值。
           而 D d =(D)(new A());就等同于D d = new A();     //这里应该看得懂是什么转型了吧!
3.以上两者有什么区别?
楼主想问的是数据类型的强制转换和引用类型的强制转换有什么区别吧?

数据类型可以转换成数据类型比自己大的,也可以转换成数据类型比自己小的
而引用类型只能把父类强转为子类,而不能把子类强制转换成父类。
作者: yunfeng482    时间: 2016-3-10 00:22
过来看看,牢固基础知识。
作者: wx_QrM5tXqT    时间: 2016-3-11 21:40
你说的这个问题在多态中是存在的。向上转型格式:父类名 f = new 子类名();即父类引用指向子类对象;向下转型格式:子类名 z = (子类名)f; 此处注意:必须要先有向上转型,才能有向下转型存在;A,B,C是多层继承关系(A继承与B继承与C;D是A的接口,也就相当于干爹吧,也算是一种继承),根据继承原则 C c = new A();这是向上转型,即父类引用指向子类对象, D d = (D)c;这个就是向下转型啦,这样转型多是为了实现子类(也就是D)的特有功能,但D是接口,那么就需要实现类重写D中的所有方法(实现类重写的方法别忘了都要是public的才可以,因为子类重写不能降低父类访问权限);下个问题:①属于基本类型转换了,int i = a; 这是隐式地将short型转换成int型变量,是基本数据类型提升;a = (short)i;这个便是强制类型转换了,但这样容易损伤精度,容易出问题的。至于②则是引用数据类型转换了,A a = new A();这个创建对象(或叫实例化)就没什么可说的了,C c = a;这个相当于C c = new A();基于子父类关系,这还是向上转型,原理同上,有了向上转型的基础条件,这个A a1 = (A)c;便是向下转型喽,作用就是为了实现A中不同于父类C的特殊功能,其实这正是多态的弊端。下面的这个判断语句你可以参考 if(k instantsof a) {...
作者: wx_QrM5tXqT    时间: 2016-3-11 21:41
你说的这个问题在多态中是存在的。向上转型格式:父类名 f = new 子类名();即父类引用指向子类对象;向下转型格式:子类名 z = (子类名)f; 此处注意:必须要先有向上转型,才能有向下转型存在;A,B,C是多层继承关系(A继承与B继承与C;D是A的接口,也就相当于干爹吧,也算是一种继承),根据继承原则 C c = new A();这是向上转型,即父类引用指向子类对象, D d = (D)c;这个就是向下转型啦,这样转型多是为了实现子类(也就是D)的特有功能,但D是接口,那么就需要实现类重写D中的所有方法(实现类重写的方法别忘了都要是public的才可以,因为子类重写不能降低父类访问权限);下个问题:①属于基本类型转换了,int i = a; 这是隐式地将short型转换成int型变量,是基本数据类型提升;a = (short)i;这个便是强制类型转换了,但这样容易损伤精度,容易出问题的。至于②则是引用数据类型转换了,A a = new A();这个创建对象(或叫实例化)就没什么可说的了,C c = a;这个相当于C c = new A();基于子父类关系,这还是向上转型,原理同上,有了向上转型的基础条件,这个A a1 = (A)c;便是向下转型喽,作用就是为了实现A中不同于父类C的特殊功能,其实这正是多态的弊端。下面的这个判断语句你可以参考 if(k instantsof a) {...
作者: wx_QrM5tXqT    时间: 2016-3-11 21:43
你说的这个问题在多态中是存在的。向上转型格式:父类名 f = new 子类名();即父类引用指向子类对象;向下转型格式:子类名 z = (子类名)f; 此处注意:必须要先有向上转型,才能有向下转型存在;A,B,C是多层继承关系(A继承与B继承与C;D是A的接口,也就相当于干爹吧,也算是一种继承),根据继承原则 C c = new A();这是向上转型,即父类引用指向子类对象, D d = (D)c;这个就是向下转型啦,这样转型多是为了实现子类(也就是D)的特有功能,但D是接口,那么就需要实现类重写D中的所有方法(实现类重写的方法别忘了都要是public的才可以,因为子类重写不能降低父类访问权限);下个问题:①属于基本类型转换了,int i = a; 这是隐式地将short型转换成int型变量,是基本数据类型提升;a = (short)i;这个便是强制类型转换了,但这样容易损伤精度,容易出问题的。至于②则是引用数据类型转换了,A a = new A();这个创建对象(或叫实例化)就没什么可说的了,C c = a;这个相当于C c = new A();基于子父类关系,这还是向上转型,原理同上,有了向上转型的基础条件,这个A a1 = (A)c;便是向下转型喽,作用就是为了实现A中不同于父类C的特殊功能,其实这正是多态的弊端。下面的这个判断语句你可以参考 if(k instantsof a) {...
作者: wx_QrM5tXqT    时间: 2016-3-11 21:44
标题: 这网太卡了。。。。。
本帖最后由 wx_QrM5tXqT 于 2016-3-11 21:47 编辑

你说的这个问题在多态中是存在的。向上转型格式:父类名 f = new 子类名();即父类引用指向子类对象;向下转型格式:子类名 z = (子类名)f; 此处注意:必须要先有向上转型,才能有向下转型存在;A,B,C是多层继承关系(A继承与B继承与C;D是A的接口,也就相当于干爹吧,也算是一种继承),根据继承原则 C c = new A();这是向上转型,即父类引用指向子类对象, D d = (D)c;这个就是向下转型啦,这样转型多是为了实现子类(也就是D)的特有功能,但D是接口,那么就需要实现类重写D中的所有方法(实现类重写的方法别忘了都要是public的才可以,因为子类重写不能降低父类访问权限);下个问题:①属于基本类型转换了,int i = a; 这是隐式地将short型转换成int型变量,是基本数据类型提升;a = (short)i;这个便是强制类型转换了,但这样容易损伤精度,容易出问题的。至于②则是引用数据类型转换了,A a = new A();这个创建对象(或叫实例化)就没什么可说的了,C c = a;这个相当于C c = new A();基于子父类关系,这还是向上转型,原理同上,有了向上转型的基础条件,这个A a1 = (A)c;便是向下转型喽,作用就是为了实现A中不同于父类C的特殊功能,其实这正是多态的弊端。下面的这个判断语句你可以参考 if(k instantsof a) {...
作者: wy580231    时间: 2016-3-16 22:43
应该是向下转型
作者: skxy2016    时间: 2016-3-22 18:51
向上转型,转为抽象了
作者: 飞扬的king    时间: 2016-3-23 21:44
向上转型
作者: アカツキ    时间: 2016-3-23 23:22
(D)c 向上转型 其他不会
作者: chaojiwudi    时间: 2016-3-26 20:20
向上转型 就是提升   向下转型 就是下降
作者: 眯眯神    时间: 2016-3-26 23:34
我觉着吧,D和C没啥直接关系,,由于D是接口没有对象,所以D类型应该是实现类A的类型,吧C类型的C强转为C的子类的子类的A类型应该是向下转型,
转型就是归属的类变了呗,比如用创建父类对象接收一个子类对象就是向上转型,子类接收父类就是向下转型,但是由于子类内容比父类多,要是这个父类不是之前转型下去的,就不能填满子类,应该会报错
至于区别,上面是一般数据类型,下面是引用,上面的强转看的是取值范围,下面的强转看的是属性的多少
我是这样理解的
作者: 1620698398    时间: 2016-3-27 11:36
D和C没有关系,(D)和C不具备向上和向下转型的条件

作者: gaoduilaile    时间: 2016-3-28 21:37
* 向上转型    说明C这个类也继承了接口D
* 转型是多态的一个特点,就是指存在子父类关系了的两个类 ,数据类型可以相互转换
* 1是基本类型数据的强制类型转换
* 2是引用类型数据的转型,是由多态实现的
作者: guojiedong    时间: 2016-4-12 22:30
向上转型
作者: AAAheilong    时间: 2016-4-14 22:00
D(接口)和C(类)只能是实现关系,而且是类实现接口.
(D)c是向下转型,   转型可以看成不同的标准转化成同一个标准.    转型实现:一是强制转型(向下转型),一是提升转型(小标准自动适应大标准.
1是数据类型,存储空间大小标准不一样,2是子父类继承关系,权限不一样,但是可以相同理解!

希望可以帮到你!





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