`
liudaoru
  • 浏览: 1575972 次
  • 性别: 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`。 ...

    RuoYi-Vue 全新 Pro 版本,优化重构所有功能

    RuoYi-Vue 全新 Pro 版本,优化重构所有功能。基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 微信小程序,支持 RBAC 动态权限、数据权限、SaaS 多租户、Flowable 工作流、三方登录、支付、短信、商城、CRM、ERP、AI 等功能

    (源码)基于Spring Boot和MyBatis的订餐管理系统.zip

    # 基于Spring Boot和MyBatis的订餐管理系统 ## 项目简介 本项目是一个基于Spring Boot和MyBatis框架的订餐管理系统,旨在提供一个高效、易用的在线订餐平台。系统分为客户端和后台管理系统两部分,客户端面向普通用户,提供用户登录、退出、菜品订购和查看订单等功能后台管理系统面向管理员,提供管理员登录、退出、菜品管理(添加、查询、修改、删除)、订单处理、用户管理(添加、查询、删除)等功能。 ## 项目的主要特性和功能 ### 客户端功能 用户登录与退出用户可以通过系统进行登录和退出操作。 菜品订购用户可以浏览菜单并选择菜品进行订购。 查看订单用户可以查看自己的订单历史。 ### 后台管理系统功能 管理员登录与退出管理员可以通过系统进行登录和退出操作。 菜品管理 添加菜品管理员可以添加新的菜品到菜单中。 查询菜品管理员可以查询现有的菜品信息。 修改菜品管理员可以修改菜品的详细信息。

    Untitled Page.pdf

    Untitled Page.pdf

    CocosCreator开发视频教程含源码简易塔防开发3.61G

    CocosCreator开发视频教程含源码简易塔防开发3.61G提取方式是百度网盘分享地址

    (源码)基于Java的票务管理系统.zip

    # 基于Java的票务管理系统 ## 项目简介 本项目是一个基于Java的票务管理系统,旨在提供一个全面的票务管理解决方案,包括购票、退票、销售状态查询等功能。系统通过Java的Servlet技术处理HTTP请求,并与MySQL数据库进行交互,确保数据的准确性和一致性。 ## 项目的主要特性和功能 1. 购票功能用户可以通过系统购买票务,系统会记录购票信息并更新数据库。 2. 退票功能用户可以申请退票,系统会处理退票请求并更新票务状态。 3. 销售状态查询管理员可以查询特定用户或特定时间段的销售状态,包括月销售、类型销售等。 4. 用户登录验证系统提供用户登录验证功能,确保只有授权用户才能进行相关操作。 5. 数据库存储所有票务信息、用户信息和销售记录都存储在MySQL数据库中,确保数据的安全性和持久性。 ## 安装使用步骤 1. 环境准备 安装Java开发环境(JDK)。

    数据库开发学习教程(从基础到进阶逐步掌握数据库的设计、开发和优化技巧)

    本教程旨在帮助学习者从基础到进阶掌握数据库开发的核心技能。通过对数据库管理系统的安装、SQL 查询语言、数据库设计、查询优化、事务管理、数据库安全等方面的详细讲解,本教程为学习者提供了全面的数据库开发知识。通过实际操作和最佳实践的学习,你将能够设计高效、稳定的数据库系统,并有效地管理和优化数据存储与访问。

    (源码)基于MCU和C语言的数字时钟系统.zip

    # 基于MCU和C语言的数字时钟系统 ## 项目简介 这是一个数字时钟系统的设计与实现项目,结合了电路设计与嵌入式编程技术。本项目包含了电路设计、PCB板设计和基于微控制器(MSP4302553)的C语言程序开发。数字时钟功能包括时间显示、闹钟提醒等。 ## 项目的主要特性和功能 1. 基于微控制器MSP4302553实现数字时钟功能。 2. 支持时间显示,包括小时、分钟和秒。 3. 支持闹钟提醒功能。 4. PCB板设计,方便硬件制作和集成。 ## 安装使用步骤 假设用户已经下载了本项目的源码文件和相关硬件设计文件。 1. 安装并熟悉MSP430微控制器的编程环境,如Energia IDE。 2. 根据提供的PCB设计文件制作硬件电路,确保电路连接正确无误。 3. 将编译好的C语言程序烧录到MSP430微控制器中。 4. 完成硬件电路的组装和调试。确保数字时钟正常工作,显示时间准确。

    基于springboot推荐算法的在线课程推荐系统源码数据库文档.zip

    基于springboot推荐算法的在线课程推荐系统源码数据库文档.zip

    华为手机助手14.0.0.320

    华为手机助手14.0.0.320

    基于springboot+web的医疗设备管理系统源码数据库文档.zip

    基于springboot+web的医疗设备管理系统源码数据库文档.zip

    基于springboot大学生校园线上招聘系统源码数据库文档.zip

    基于springboot大学生校园线上招聘系统源码数据库文档.zip

    基于springboot校外兼职教师考勤管理系统源码数据库文档.zip

    基于springboot校外兼职教师考勤管理系统源码数据库文档.zip

    基于springboot竞赛管理系统源码数据库文档.zip

    基于springboot竞赛管理系统源码数据库文档.zip

    基于springboot的考研资讯系统源码数据库文档.zip

    基于springboot的考研资讯系统源码数据库文档.zip

    飞机大战代码文档.rar

    《飞机大战》是一款经典的游戏,其代码文档资源通常包含游戏的核心逻辑、图形界面设计、音效处理等多个方面。以下是对飞机大战代码文档资源的详细描述: 飞机大战的代码通常分为多个模块,每个模块负责不同的功能。常见的模块包括: 主程序模块:负责游戏的初始化、事件循环、碰撞检测、精灵更新和画面渲染等核心功能。 精灵模块:包含游戏中所有可见对象的类定义,如飞机、敌机、子弹、奖励物品等。这些类通常继承自pygame的Sprite类,并实现自己的绘制和更新方法。 背景模块:负责游戏背景的绘制和滚动效果。通常使用两张相同的背景图片来实现无缝滚动。 音效模块:负责游戏中的音效播放,如飞机发射子弹的声音、敌机被击中的声音等。 二、核心逻辑 游戏初始化:在游戏开始时,主程序模块会初始化游戏窗口、时钟、精灵组等对象,并加载游戏所需的图片和音效资源。 事件循环:主程序模块会不断监听用户输入和系统事件,如键盘按键、鼠标移动等,并根据事件类型执行相应的操作。

    FastReport v6.9.15 Enterprise FS for Delphi 11.0

    FastReport v6.9.15 Enterprise FS for Delphi 11.0 概览 欢迎使用FastReport v6.9.15 Enterprise FS 版本,这是一款专为Delphi 7至11.0设计的高效、强大的报表生成工具。FastReport以其易用性、丰富的功能和高性能,在Delphi开发社区中享有盛誉。此版本特别适配于Delphi 11.0环境,为企业级应用提供了完整的报表解决方案。 特性亮点 全面兼容:无缝集成于Delphi 7到11.0的所有版本,确保在最新的开发平台上也能稳定工作。 企业级功能:包括数据处理、图表展示、多层嵌套报表等高级特性,满足复杂报表的设计需求。 高速渲染:优化的渲染引擎使得大数据量报表的生成快速流畅。 可视化设计:直观的设计器界面,让开发者能够轻松创建和编辑报表模板。 多种导出格式:支持将报表导出为PDF、Excel、HTML等多种格式,便于数据分享和分析。 源码级集成(FS版本特色):提供源代码,便于深度定制和二次开发。 安装与使用 请先解压缩FastReport v6.9.15 Enterprise FS Delph

Global site tag (gtag.js) - Google Analytics