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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© zhouxp3323 黑马帝   /  2012-3-19 19:37  /  2492 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

向上转型和向下转型是什么回事,谁能举些例子说明下吗?

9 个回复

正序浏览
郑涛 中级黑马 2012-3-20 00:00:08
9#
多态中的概念。向上转型出现在有继承或实现关系的类间,且只能是子类通过向上转型成为父类对象的引用,如Animal  animal=new Dog(),通俗说就是,狗是动物,但动物不是狗。向下转型最常见例子是,集合框架中,如ArrayList中存放Object对象为最高类型,操作时要用  (子类名)对象 (**这个对象就是Object类型的**)进行 强制转换。
回复 使用道具 举报
        如现在有动物、鸟类、燕子三个名词,他们之间有什么关系呢?通常我们都会说,燕子是特殊的鸟类,或者说燕子是鸟类的一种。为此,从对象的定义来 看,鸟类就是一个父类,而燕子就是一个子类。或者说,燕子对象就是一个鸟类对象。要强调的一点就是,由于燕子是鸟类的一个对象,所以鸟类所具有的特性燕子全部具有。而燕子所具有的特性(如迁徙)则鸟类不一定都具有。在这个例子中,燕子也是一种鸟类。为此可以将燕子的对象堪称是一个鸟类的对象。这种 方法在Java语言环境中就叫做“向上转型”。从这个例子中可以看出,向上转型是一个从较抽象类型的类(鸟类)向比较 具体的类(燕子)过度。由于具体类(燕子)具有抽象类(鸟类)的全部特性,所以在这个转换过程中是不会有问题的。这就好像一个逻辑判断题说燕子是鸟类的一 种,其具有鸟类的全部特性。这个命题至少到现在为止是完全正确的。
        但是,在实际工作中,我们还经常会遇到向下转型的情况。也就是说从一个抽象类中(鸟类)引用具体类(燕子)中的对象。也就是说,我们可以说燕子 是鸟类的一种。但是现在反过来,如果说鸟类就是燕子,那显然就是以偏概全了,因为燕子并不具有其他鸟类的特性。如鸽子的特性燕子就没有。所以,在应用程序 开发中,如果将父类对象赋值给子类的对象,就可能有问题。如果硬要这么做的话,则很有可能发生编译器错误。因为父类对象并不一定是子类的实例。这是什么意 思呢?即所说的鸟类(父类对象)并不一定是子类对象(燕子)。因为鸟类对象还有可能是鸽子、白鹭等等。所以,如果将父类对象给子类对象的话,那么就会出现问题。
        由于向上转型一般都是安全的,即将一个子类对象直 接赋值给父类对象,一般被认为是安全的,如燕子是鸟类在哪里都是成立的。所以在向上转型时不需要采用其他的关键字,我们常常把向上转换叫做隐式转换。但是在这里向下转换是一种不安全的转换方式,如说鸟类就是燕子, 这种说法无论在哪里都说不过去。为此默认情况下,进行向下转型时,往往会发生编译器错误。
        一般情况下,越是具体的对象所具有的特性越多。如燕子的特性就比鸟类的特性多的多。而越抽象的对象反而具有的特性越少,因为其只具有一些抽象对象的共性特征。在进行向下转型操作时,将特性范围小的对象转换为特性范围大的对象肯定会出现问题。为此在向下转型时,必须确保转换后不会出现问题,即具体 对象的特性在抽象对象中也全部具备,只有如此才能够进行转换。而且即使满足这个条件,编译器也不不能够进行隐式转换。而是需要采用关键字进行强制转换。如 子类对象名字=(子类名)父类对象名字。如果上面这个语法,就可以实现对象类型的强制转换。
        在进行向下转型时一定要进行强制转换。即通过子类对象名字=(子类名)父类对象名字进行赋值,而不能够向向上转型那样进行隐式转换。
        从以上分析中可以看出,向下转型往往被认为是不安全的。当在程序中执行向下转型操作的时候,如果父类对象不是子类对象的实例,就会发生编译器错 误。所以在执行向下转型之前要先作一件事情,就是判断父类对象是否为子类对象的实例。也就是说,先要想一想,燕子就是鸟类这个命题是否成立(在某些特定的 情况下这个伪命题可能会成立,如燕子的特性与鸟类的特性完全一致)。只有如此,向下转型才不会出现问题。在进行向下转型操作时,将特性范围小的对象转换为 特性范围大的对象肯定会出现问题。但是,如果两个转换的对象特性范围一样大的话,可那么就不会有问题了。
在进行向下转型时,需要注意以下几方面的内容:
        一是要慎用向下转型。由于向下转型容易出问题,为此不到万不得已的时候,最好不用使用向下转型。条条道路通罗马,如果在编程之前,合理规划类,往往可以避免向下转型的发生。只有其他路走不通的情况下,才考虑通过向下转型的技术来解决问题。
        二是在进行向下转型的时候,需要做两件事情。一是一定要使用instanceof操作符来判断转型的合法性,即判断父类对象是否为子类对象的实 例。这就好像在编写四则运算时,要判断除数不为零一样。这是必须要做的。也是程序员必须要养成的一个习惯。在进行向下转型时,就自然而然会想到需要进行这 个判断。只有如此,应用程序的错误才能够降低。而且还能够满足不同的需求。二是需要注意向上转型与向下转型的区别。一般情况下,向上转型往往被认为是安全 的,所以在Java语言平台中向上转型采用的是隐式转型。而向下转型由于特性范围大小的不同,为此往往被认为是不安全的。故系统默认情况下进行向下转型时 必须采用强制转型的方式。如果不采用强制转型,则即使满足向下转型的条件,其也会发生编译器错误。所以需要切记,向下转型必须要采用强制转型。
        三是需要做好备注等注释工作。由于像向下转型等操作是容易出现问题的地方。为此在进行类似的操作时,最好在行注释或者块注释中能够进行说明。这对于后续的维护与代码的升级是很有帮助的。好记性不如烂笔头。如果没有做好相关注释的话,这次可能没有问题,但是下次再代码升级或者其他原因需要调整或者 重写原有的代码时,就可能会因为疏忽而导致转型的失败。
        向上转型大家可以放心大胆的用。但是在使用向下转型技术时,大家要慎重,要按部就班(先判断后使用)的进行操作。
回复 使用道具 举报
魏群 黑马帝 2012-3-19 22:05:10
7#
举个例子:有2个类,Father是父类,Son类继承自Father。
Father f1 = new Son();   // 这就叫 upcasting (向上转型)
// 现在f1引用指向一个Son对象
Son s1 = (Son)f1;   // 这就叫 downcasting (向下转型)
// 现在f1还是指向Son对象
第2个例子:
Father f2 = new Father();
Son s2 = (Son)f2;       // 出错,子类引用不能指向父类对象
只要记住只能父类引用指向子类对象,  而子类引用不能指向父类对象就行了。
回复 使用道具 举报
多态:每个类都有自己的成员,访问权限,不一定所有人都可以使用它,继承的话可以重载重写父类方法,
向下转型:父类不一定能转成子类类型
向上转型:子类一定能转成父类类型

视频中的例子:人有男人女人,向下转型的话人不一定只是男人,向上转型的话男人是人。
回复 使用道具 举报
向上向下转型中的上和下是指继承树中的上层和下层,上层表示父类以及更上层,下层表示此类的子类或更下层。
向上转型:Animal animal = new Cat(),其中Cat类继承Animal类或者是实现Animal接口,我们现在的把新new出来的Cat对象赋值给一个Animal的引用就是向上转型,我们用animal变量只能得到Cat中的部分方法和Animal的全部方法。
向下转型:Cat cat = (Cat)animal,这里我们用强制类型转换到子类Cat类型。
在向上转型中我们无需加强制类型转换,但是在向下转型中我们必须加上强制类型转换,否则编译器编译不通过。
回复 使用道具 举报
转换可分为向上类型转换盒向下类型转换
向上类型转换(:比如说将 Cat类型转换为Animal类型 ,即将子转换为父类型。对于向上,不需要显式指定
向下类型转换( downcast):比如将 ):比如将 Animal 类型转换为 Cat 类型 。即将父转换为子类型。对于向下,必须要显式指定(必须要使用强制类型 转换) 。
回复 使用道具 举报
如果A继承B  那么B a=new A(),表示将a向上转型,
反之
B a = new A();
A b =A(a);
就是吧原本B类型的对象 转成了他的子类型 即向下转型!
回复 使用道具 举报
如果A是B的父类,A a=new B(),这是向上转型,很少用到向下转型吧
回复 使用道具 举报
class Person
{
        public void show()
        {
        }
}
class Student extends Person
{
        public void show()
        {}
        public void study()
        {}
}
Person stu = new Student();
stu.show;
Student s=(Student)stu;
s.study();

Person 的引用stu 指向子类对象 Student
   可以直接调用show方法是因为父类和子类都用show方法
   也就是说子类方法覆盖了父类的方法  像这种方法可以用父类
   引用直接调用  因为stu的类型是属于父类Person的
   而你如果想调用子类特有的方法的话,就不能用父类的引用stu
   来直接调用了 就必须把父类引用stu向下转型成子类引用
   即 Student s=(Student)stu;   然后在通过s引用调用子类特有的方法

评分

参与人数 1技术分 +1 收起 理由
房宝彬 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马