`
liudaoru
  • 浏览: 1586743 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java中向上转型(upcast)和向下转型(downcast)

    博客分类:
  • java
阅读更多

From: http://blog.csdn.net/zhu_apollo/archive/2007/11/26/1903374.aspx

 

class Useful

{
 int value = 20;
public void f() {System.out.println("f() in the Useful class");}
public void g() {System.out.println("g() in the Useful class");}
}

class MoreUseful extends Useful {
 int value = 21;
public void f() {System.out.println("f() in the MoreUseful class");}
public void g() {System.out.println("g() in the MoreUseful class");}
public void u() {System.out.println("u() in the MoreUseful class");}
public void v() {}
public void w() {}
}

class MoreUseful2 extends Useful {
 int value = 21;
public void f() {System.out.println("f() in the MoreUseful2 class");}
public void g() {System.out.println("g() in the MoreUseful2 class");}
public void u() {System.out.println("u() in the MoreUseful2 class");}
public void v() {}
public void w() {}
}


class ExtendsMoreUseful2 extends MoreUseful2 {
 int value = 22;
public void f() {System.out.println("f() in the ExtendsMoreUseful2 class");}
public void g() {System.out.println("g() in the ExtendsMoreUseful2 class");}
public void u() {System.out.println("u() in the ExtendsMoreUseful2 class");}
public void v() {}
public void w() {}
}

public class RTTI {
public static void main(String[] args) {
 
 //Useful useful = new MoreUseful();
 //useful.u();   //这是错误的,u()方法没有在useful类型中调用。

         Useful[] x =
         {
          new Useful(),
          new MoreUseful(),
          new MoreUseful2(),
          new ExtendsMoreUseful2()
          }; //声明一个变量数组,保存每个Useful对象的引用,
             //那么每一个Useful对象就会自动向上转型为Useful。

for(int i=0;i<x.length;i++)
{
 if(x[i] instanceof MoreUseful2)  //判断instanceof左边的对象是否是右边的类的实例。
 {
  MoreUseful2 moreuseful2 = (MoreUseful2)x[i];//向下转型(具体解释见下面的分析)
  moreuseful2.u();
 }

 x[i].g(); //这是动态绑定,将方法的调用和方法主体关联起来就是动态绑定。
 
}

运行结果:

g() in the Useful class        // 由于x[0].g()这一句中调用g()方法实际的对象类型是

                                            // 基类Useful类型,故将调用基类中的f()方法。(没有转型)
                              

g() in the MoreUseful class      // 由于x[1].g()这一句中调用g()方法实际的对象类型是

                                                   //子类Moreuseful类型,故将调用子类Moreuseful中

                                                  //  覆盖父 类的g()方法。(向上转型)
                                   

u() in the MoreUseful2 class        // 由于x[2]是MoreUseful2类型,故可以对其向下转型调

                                                        // 用MoreUseful2中的扩展方法u()。(向下转型)

 

g() in the MoreUseful2 class        // 又x[2].g()这一句中调用g()方法实际的对象类型是子

                                                       // 类Moreuseful类型,故将调用子类Moreuseful中
                                                      //  覆盖父类的g()方法。(向上转型)

 

u() in the ExtendsMoreUseful2 class    // 由于x[3]是ExtendMoreUseful2类型,

                                   // 它是MoreUseful2的子类,存在is-a关系,故可以对其向下转

                         //  型,将调ExtendMoreUseful2中的扩展的方法u()。(向下转型)

 

g() in the ExtendsMoreUseful2 class     // 又x[3].g()这一句中调用g()方法实际的对象类型

                                                                   //是子类ExtendMoreuseful类型故将调用
                                    // 子类ExtendMoreuseful中覆盖父类的g()方法。(向上转型)


分析和结论:

(一)向上转型

(1)定义: 把对某个对象的引用视为对其基类引用的做法被称为“向上转型”。
    
这主要是由于子类的对象可以看成是基类的对象这原因而得来的,也就是具有is-a关系。

 

比如:
     Useful useful = new MoreUseful();//右边是一个子类的对象,而左边是一个父类类型
                                      //的变量,指向右边的子类对象。

(2)基类可以接收发给导出类的任何消息,因为二者有完全相同的接口,我们只需要

导出类向上转型,永远不需要知道正在处理的对象的确切类型,这也就是多态性决

定的。利用多态性,具有同样方法名和方法特征的方法根据调用方法的对象的类型,

可以产生不同的动作,这极大地增加了程序员的表达能力。


     回头再看一看上面这个例子中的一段for循环代码,

for(int i=0;i<x.length;i++)
{
 if(x[i] instanceof MoreUseful2)   //判断instanceof左边的对象是否是右边的类的实例。
 {
  MoreUseful2 moreuseful2 = (MoreUseful2)x[i];  //向下转型(具体解释见下面的分析)
  moreuseful2.u();
 }

 x[i].g(); //动态绑定
 
}
    
主要看x[i].g();这一句话,现在我们还不知道x[i]这个到底是指代哪一个Useful对象,

在这种情况下,编译器是怎么知道调用哪个方法的呢?这是一个动态绑定的问题,见

下面。

(二)动态绑定

(1)定义:将方法的调用和方法主体关联起来就是动态绑定。

比如:x[i].g();这就是一个动态绑定,x[i]是一个对象类型,g()是一个不知道是属于

哪个对象的方法,将这两个两个联合在一起,就是一个绑定。

(2)要注意:Java中除了static和final方法(private方法属于final方法,因为fianl方法

不可以覆盖,static方法是一个全局方法,属于所有类共享,不在多态范围内)之外,

其他所有的方法都是动态绑定,这就意味着在通常情况下,我们不必判定是否应该进

行动态绑定,因为这个会自动发生。

(3)接着上面的答复。编译器是怎么知道调用哪个方法的呢?

主要还是x[i].g();这一句话的作用,x[i]在调用方法的时候,会调用“实际”的方法,这

实际的方法由所引用的对象的类型决定。那么调用的实际方法可能是父类中没有被

子类覆盖的方法,也可能是子类中覆盖父类的方法,主要看调用这个方法的实际的对

象类型是哪一个。


(三)向下转型

既然有向上转型,那么有没有向下转型呢?

答:有

(1)概述

继承可以确保所有的子类类具有基类的接口,且绝对不会少。那么子类除了有父类的

方法,也可以有自己的额外的新方法(这些方法是基类所没有的),那么一旦向上转

型,就不能调用子类中的新方法,那么能不能用一种方式调用这些新方法呢?当然有

了,这时候就需要向下转型。

(2)向下转型

将超类的引用强制转换为子类类型就叫做向下转型。

注意:将超类的引用赋给为子类类型的变量(没有进行显示地强制转换)是一个编译

错误。

例子:

还是上面的for循环代码

for(int i=0;i<x.length;i++)
{
 if(x[i] instanceof MoreUseful2) //     判断instanceof左边的对象是否是右边的类的实例。
 {
  MoreUseful2 moreuseful2 = (MoreUseful2)x[i]; //  向下转型
  moreuseful2.u();
 }

 x[i].g();
 
}


分析:x[i]可以代表具体的Useful对象类型,当它是MoreUseful2或ExtendsMoreUseful2

对象类型时,就可以调用该对象的额外方法u(),v(),w(),也就是当对象x[i]和Moreusful对

象存在is-a关系时,才可以进行向下转型,如果要转换的对象类型与指定的对象类型不

存在is-a关系时,会产生一个ClassCastException异常。

 

总之:

向下转型时,对象只能强制转换为其本身类型或者其超类类型。比如,

当x[i]ExtendsMoreUseful2对时,可以把他转换为其本身ExtendsMoreUseful2对象类

型,也可以把它转换为其基类MoreUseful2类型。但是在编译时候还不知道这个x[i]是代

表那个具体对象类型只知道这个x[i]是基类类型引用,所以要用这样的形式" (想要要得

到的类型)x[i] " 进行转换。x[i]在这里是就我这个例子来说明的,你也可以使用其它的

英文代替,其意义是一切符合规定的需要被转换的对象。

 

下面还有个关于向上转型和向下转型的例子, 

 

abstract class ClassAbstract1{}
class ClassDerived1 extends ClassAbstract1
{
 public void play1()
 {
  System.out.println("play1() is in the ClassDerived1");
 }
}
abstract class ClassAbstract2{public abstract void play2();}
class ClassDerived2 extends ClassAbstract2
{
 public void play2()
 {
  System.out.println("play2() is in the ClassDerived2");
 }
}


public class E14_UnCast {
 
 public static void playDemo1(ClassAbstract1 ObjectParameter)
 {
  ((ClassDerived1)ObjectParameter).play1();//向下转型,可以调用导出类中的扩展方法
 }
 
 public static void playDemo2(ClassAbstract2 ObjectParameter)
 {
  ObjectParameter.play2();//向上转型,可以调用导出类中的覆盖方法
 }

 /**
  * @param args
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  ClassAbstract1 classabstract = new ClassDerived1();
  playDemo1(classabstract);
  ClassAbstract2 classabstract2 = new ClassDerived2();
  playDemo2(classabstract2);

 }

}


运行结果:
play1() is in the ClassDerived1
play2() is in the ClassDerived2

 

分享到:
评论

相关推荐

    收集的电子书 Java SE Lesson 2

    2. 类型转换:Java支持两种类型转换,向上类型转换(upcast)和向下类型转换(downcast)。向上类型转换是将子类对象转换为父类类型,这种转换是隐式的,安全的。而向下类型转换是将父类对象显式地转换为子类类型,...

    Java基础教程之类型转换与多态

    Java中的类型转换与多态是面向对象编程的重要概念,它们为程序设计提供了灵活性和扩展性。类型转换允许我们在不同数据类型之间转换,而多态则让代码能够处理多种类型的对象。 首先,我们来讨论类型检查。Java作为一...

    CKEditor5-SyntaxHighlight.v1.0.4.zip

    在ASP.NET Web窗体项目中,我们可以利用CKEditor 5的API和插件系统来扩展其功能。 接下来,我们要引入highlight.js。这个库支持多种编程语言的语法高亮,并且样式可定制,可以轻松适应不同的网站设计。通过将...

    gdb命令速查1

    9. **向上或向下切换函数堆栈帧**:`up`和`down`。 ### 断点管理 1. **在匿名空间设置断点**:使用`break *address`。 2. **在程序地址上打断点**:`break address`。 3. **在程序入口处打断点**:`break main`。 ...

    基于A*算法的往返式全覆盖路径规划改进及其Matlab实现

    内容概要:本文详细介绍了如何利用A*算法改进传统的往返式路径规划,解决扫地机器人在复杂环境中容易卡住的问题。首先构建了一个可视化的栅格地图用于模拟环境,然后引入了优先级运动规则,使机器人能够有规律地进行往返清扫。当遇到死角时,通过A*算法计算最佳逃生路径,确保机器人能够顺利脱困并继续完成清扫任务。实验结果显示,改进后的算法显著提高了清洁覆盖率,降低了路径重复率。此外,还讨论了一些潜在的优化方向,如动态调整启发函数权重、断点续传以及能耗模型等。 适合人群:对路径规划算法感兴趣的科研人员、自动化专业学生、扫地机器人开发者。 使用场景及目标:适用于需要高覆盖率和低重复率的室内清洁任务,旨在提高扫地机器人的工作效率和智能化水平。 其他说明:文中提供了详细的Matlab代码实现,并附带了仿真测试结果,有助于读者理解和复现该算法。

    爬取喜马拉雅听书(1).py

    爬取喜马拉雅听书(1)

    安卓向上传递数据学习笔记总结

    安卓向上传递数据学习笔记总结

    tigervnc-selinux-1.11.0-9.el8.x64-86.rpm.tar.gz

    1、文件说明: Centos8操作系统tigervnc-selinux-1.11.0-9.el8.rpm以及相关依赖,全打包为一个tar.gz压缩包 2、安装指令: #Step1、解压 tar -zxvf tigervnc-selinux-1.11.0-9.el8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm

    户外储能电源双向逆变器板生产资料及技术规格详解

    内容概要:本文详细介绍了户外储能电源双向逆变器板的技术资料及其特点。涵盖原理文件、PCB文件、源代码、电感与变压器规格参数等,适用于2KW(最大3KW)的户外储能电源。文中强调了双向软开关DC-DC设计、两颗M0+ 32位MCU的分工、SPWM调制方式、H桥IGBT的应用、详细的电气参数和技术特性。此外,还包括了SPWM信号生成代码示例、硬件设计细节、生产注意事项等。 适合人群:从事户外储能电源开发的技术人员、电子工程师、产品经理等。 使用场景及目标:帮助开发者快速掌握双向逆变器板的设计和生产要点,缩短产品研发周期,提高产品质量和可靠性。具体应用场景包括但不限于户外应急电源、便携式储能设备等。 其他说明:本文提供了丰富的技术细节和实践经验,如双向软开关DC-DC设计、SPWM调制、IGBT驱动、EMC整改记录等,有助于解决实际开发中的难题。同时,附带的实际案例展示了该方案的成功应用,进一步证明了其可行性和优越性。

    电能质量分析:间谐波分析.zip

    电子仿真教程,从基础到精通,每个压缩包15篇教程,每篇教程5000字以上。

    【计算机科学领域】美国计算机学会(ACM):组织架构、使命愿景、核心价值及活动项目介绍

    内容概要:美国计算机学会(ACM)是一个成立于1947年的国际性计算机专业组织,致力于推动计算机科学的发展,提供教育、资源和专业发展机会。ACM的使命是促进计算机科学和信息技术领域的进步,愿景是成为全球计算机专业人士的首选组织。其核心价值包括卓越、诚信、包容性、合作和创新。ACM定期举办学术会议,如SIGGRAPH和图灵奖颁奖典礼,出版高质量的学术期刊和会议论文集,涵盖人工智能、软件工程、网络安全等领域。此外,ACM还提供在线课程、研讨会、认证项目等教育资源,以及职业规划、网络机会和领导力培训等职业发展服务。ACM图灵奖被誉为“计算机界的诺贝尔奖”,每年颁发给对计算机科学和技术做出重大贡献的个人。; 适合人群:计算机科学领域的专业人士、教育工作者、工程师和学生。; 使用场景及目标:①了解计算机科学领域的最新研究成果和发展趋势;②获取高质量的教育资源和职业发展机会;③参与计算机科学领域的学术交流和合作。; 其他说明:ACM作为一个全球性的组织,在教育、研究和行业实践中发挥着重要作用,推动了技术创新和社会进步。

    最新版logstash-8.17.4-windows-x86-64.zip

    logstash-8.17.4-windows-x86_64.zip

    一个基于Springboot使用Aspect实现一个切面,以记录日志为例

    springboot 一个基于Springboot使用Aspect实现一个切面,以记录日志为例

    音箱底部折边设备sw22可编辑_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    音箱底部折边设备sw22可编辑_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    基于Python Django MySQL的个性化图书推荐系统:协同过滤算法及远程部署实现

    内容概要:本文详细介绍了如何使用Python、Django和MySQL构建一个完整的个性化图书推荐系统。系统从前端界面设计、后端逻辑实现到数据库设计,涵盖了用户管理、图书管理、评分系统等功能模块。重点讲解了基于用户和项目的协同过滤算法实现,以及在用户评分数据不足时的标签推荐备份方案。此外,还包括了系统部署、测试和优化的具体步骤,如云服务器部署、性能测试、数据库优化等。 适合人群:具备一定Python和Web开发基础的研发人员,尤其是对推荐系统感兴趣的技术爱好者。 使用场景及目标:适用于希望深入了解图书推荐系统的工作原理和实现细节的技术人员。目标是帮助读者掌握从零开始搭建一个完整的个性化推荐系统的方法,包括前后端开发、算法实现和系统部署。 其他说明:文中提供了大量代码示例和实战经验,如数据库设计、爬虫实现、权限管理等,有助于读者更好地理解和应用相关技术。

    Ai和python学习资料

    Ai和python学习资料

    文本摘要.py

    文本摘要

    冲击试验机sw22_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    冲击试验机sw22_三维3D设计图纸_包括零件图_机械3D图可修改打包下载_三维3D设计图纸_包括零件图_机械3D图可修改打包下载.zip

    Java开发MybatisPlus框架详解:增强Mybatis功能实现高效CRUD操作与代码生成

    内容概要:本文详细介绍了MyBatis Plus(MP),它是MyBatis的增强工具,旨在简化CRUD操作、提高开发效率。其主要功能包括内置分页插件、简化CRUD操作以及代码生成器。使用时只需引入相应依赖,自定义Mapper接口继承BaseMapper泛型接口,并通过实体类反射获取数据库表信息。文章还介绍了常用注解如@TableName、@TableId、@TableField、@TableLogic和@Version,配置项如全局配置、类型别名和Mapper文件路径,以及核心功能如批量插入、分页查询、条件构造器(Wrapper)等。此外,扩展功能涵盖逻辑删除、枚举处理器和JSON处理器,插件功能则包括分页插件的配置和使用。 适合人群:具备一定Java开发经验,尤其是熟悉MyBatis框架的开发者,特别是那些希望提高开发效率、减少重复代码的工作1-3年研发人员。 使用场景及目标:①简化数据库操作,提高开发效率;②快速生成代码,减少手动编写SQL语句的工作量;③实现分页查询、逻辑删除、枚举和JSON字段处理等高级功能,提升应用的灵活性和可维护性。 其他说明:本文不仅提供了MyBatis Plus的功能介绍和使用方法,还深入探讨了条件构造器(Wrapper)的使用技巧,帮助开发者更好地理解和掌握这一强大的工具。在实际开发中,合理利用这些功能可以显著提高开发效率和代码质量。建议在学习过程中结合具体项目实践,逐步掌握各个功能的应用场景和最佳实践。

    电路仿真:射频电路仿真.zip

    电子仿真教程,从基础到精通,每个压缩包15篇教程,每篇教程5000字以上。

Global site tag (gtag.js) - Google Analytics