(一)

先给出个例子,代码如下:

/** * @author WangQun * 动物抽象类 */ abstract class Animal { public abstract void speak(); public void eat(){ // 闷头吃,不做额外的事情 } } /** * @author WangQun * 门神接口 */ interface DoorGod { void guard(); } /** * @author WangQun * 猫,继承自动物 */ class Cat extends Animal { @Override public void eat() { try { Thread.sleep( 1000 ); } catch (InterruptedException e) { e.printStackTrace(); } super .eat(); } @Override public void speak() { System.out.println( " 喵喵 " ); } } /** * @author WangQun * 狗,继承自动物,实现门神接口 */ class Dog extends Animal implements DoorGod{ @Override public void speak() { System.out.println( " 汪汪 " ); } public void guard() { while ( true ){ System.out.println( " 汪汪 " ); } } }

其中Animal为基类,定义speak和eat方法,eat方法给出了空实现; DoorGod为门神接口,定义了 guard方法来守护家门; Cat为继承Animal的子类,这里假定猫有挑食的习惯,在eat中要耽搁点时间看看伙食;Dog也为继承Animal的子类,同时它实现了DoorGod接口来守护家门。

先说说上溯造型(upcasting)。这个术语缘于继承关系图的传统画法:将基类至于顶部,而向下发展的就是派生类。根据上面的sample,我给出下面的一个小应用:

public class Main { /** * @param animal * 上溯,传入的参数强制转换成其父类 */ public static void upcasting(Animal animal){ animal.speak(); animal.eat(); } public static void main(String[] args) { Animal dog1 = new Dog(); upcasting(dog1); Dog dog2 = new Dog(); upcasting(dog2); } }

由于upcasting(Animal animal)方法的参数是 Animal类型的,因此如果传入的参数是 Animal的子类,传入的参数就会被转换成父类Animal类型,这样你创建的Dog对象能使用的方法只是Animal中的签名方法;也就是说,在上溯的过程中,Dog的接口变窄了,它本身的一些方法(例如实现了 DoorGod的guard方法)就不可见了。如果你想使用Dog中存在而Animal中不存在的方法(比如guard方法),编译时不能通过的。由此可见,上溯造型是安全的类型转换。另一方面,虽然upcasting(Animal animal)方法的参数是 Animal类型,但传入的参数可以是Animal的派生类(这也是OO编程中惯用的编程方法),这里面就有个对象的类型识别问题,也就是运行时类型识别(run-time type identification,缩写为RTTI) ,这也可以单独写一篇文章了,《Thinking in Java》中的第10章详细地阐述了RTTI。

相对于类型转换安全的上溯造型,下溯造型就未必是安全的了。我们经常会做些强制类型转换的事情,有时我们也会无意间遇到 ClassCastException的转换异常(从这一点来说,我们应该多用范型来避免不安全的类型转换)。例如:

public static void downcasting(Animal animal){ //判断类是不是实现自哪个接口 if(animal instanceof DoorGod){ DoorGod doorGod = (DoorGod)animal; doorGod.guard(); } if(animal instanceof Cat){ Cat cat = (Cat)animal; cat.speak(); } }

如果没有采取措施(上面使用的措施是instanceof)判断对象的类型,那么向下的强制转换就是不安全的。这种转换错误在编译时是不能检测出来的,只有在运行时才会抛出 ClassCastException异常,对于测试来说,这样的错误也是很难检测的。

总的来说,上溯造型与下溯造型概念上还是很简单的。但即便最简单的东西,我们也有可能犯下错误。用了那么多的框架后,回头看看基础知识,发现自己的根基并不是想象中的牢固阿。

注:本文参考了《Thinking in Java》,这本书真需要细细品味啊!

(二)

当你拿到一个对象的引用时(例如参数),你可能需要判断这个引用真正指向的类。所以你需要从该类继承树的最底层开始,使用instanceof操作符判断,第一个结果为true的类即为引用真正指向的类。

例如下面的例子:

class Person{} class Student extends Person{} class Postgraduate extends Student{} class Animal{} public class InstanceofTester { public static void main(String[] args) { instanceofTest(new Student()); } public static void instanceofTest(Person p){ // 判断p的真正类型 if (p instanceof Postgraduate){ System.out.println("p是类Postgraduate的实例"); } else if(p instanceof Student){ System.out.println("p是类Student的实例"); } else if(p instanceof Person){ System.out.println("p是类Person的实例"); } else if(p instanceof Object) { System.out.println("p是类Object的实例"); } /*if(p instanceof Animal){//此错编译错误,所以做注释 System.out.println("p是类Animal的实例"); }*/ } }

这个程序的输出结果是:p是类Student的实例

Person类所在的继承树是:Object<--Person<--Student<--Postgraduate。

这个例子中还加入一个Animal类,它不是在Person类的继承树中,所以不能作为instanceof的右操作数。

你可以跑跑程序,应该就明白什么意思了。

Java 的上溯造型和下溯造型以及举例,以及判断参数等指向的类相关推荐

  1. java 下溯造型_Java 的上溯造型和下溯造型以及举例,以及判断参数等指向的类

    (一) 先给出个例子,代码如下: /** * @author WangQun * 动物抽象类 */ abstract class Animal { public abstract void speak ...

  2. java上溯造型与下溯造型

    Java的多态性 面向对象编程有三个特征,即封装.继承和多态. 封装隐藏了类的内部实现机制,从而可以在不影响使用者的前提下改变类的内部结构,同时保护了数据. 继承是为了重用父类代码,同时为实现多态性作 ...

  3. 学习上溯造型和下溯造型 【转载一篇】

    题按:做了几年的java程序,却很难说对基本的OO概念都有理解.即便每天都写的代码中,也很难说清楚其中到底运用了怎样的概念和思想.前日的考试中看到关于上溯造型与下溯造型的问题,就查了些资料,集中说一下 ...

  4. 上溯造型、下溯造型的理解

    (上溯造型定义:java允许把一个子类对象直接复制给一个父类引用变量,自动完成类型转换,这种语法现象称为上溯造型. 下溯造型回到它自己所在的类(强制转换):一个对象被溯型为父类或接口后还可以再被下溯造 ...

  5. Java——上溯造型下溯造型

    public abstract class Animal {public abstract void speak();public void eat(){// 吃吃吃!!! } } public in ...

  6. java 下溯造型_Java——上溯造型下溯造型

    public abstract class Animal { public abstract void speak(); public void eat(){ // 吃吃吃!!! } } public ...

  7. [Java初学]Java上溯造型(upcasting)与下溯造型(Downcasting)

    Java上溯造型(upcasting)与下溯造型(Downcasting) 上溯造型(upcasting) 这个术语缘于继承关系图的传统画法:将基类至于顶部,而向下发展的就是派生类. 文章使用的完整代 ...

  8. 上溯造型和下溯造性(解耦合)

    上溯造型: 向上转型(Upcasting)- 子类转换为父类,自动转换: 前提 - 具有继承或实现关系: 向上转换损失了子类新扩展的属性和方法,仅可以使用从父类中继承的属性和方法 Animal a=n ...

  9. java 上溯造型与下塑造型

    父类: package com.neusoft.chapter07;public class Father {public int i = 1;public void say(){System.out ...

最新文章

  1. Java后端Java面试题总结2021(春招+秋招+社招)
  2. 用STL给C++充电:第一部分
  3. 强化学习—— 蒙特卡洛树(Monte Carlo Tree Search, MCTS)
  4. 中国电力设备行业运行状况与产量趋势研究报告2022版
  5. MQ 的本质是什么呢?
  6. 项目-团队-技术-个人 (团队建设篇)
  7. JavaScript浮点运算0.2+0.1 !== 0.3
  8. 基于 FFMPEG 的音频编解码(三):音频编码
  9. StrongShop跨境电商系统源码 支持多语言多货币
  10. f1c200s核心板_F1C200s NS 2009 驱动
  11. sketchup 图片转模型_3d模型转su模型(如何将3D模型转化为sketchup)
  12. sox 音频采样率转换
  13. 教你如何写四级高分作文!!!大学英语四级常考各种类型作文模板-范文
  14. Android音视频视频基础(H264)二 SPS分析
  15. SpringBoot之RMI的简单使用
  16. node安装指定版本 (LTS 长期稳定版本,Current 最新版本)
  17. uniapp简单搞定支付
  18. 快手如何引流的话术?在快手引流精准粉丝的技巧
  19. 上了 istio 的贼船之 API Gateway
  20. iPhone 5 屏幕尺寸变长指南

热门文章

  1. Algorithm1
  2. 通过wifi对手机进行adb连接debug调试 adb connect ip_address:5555
  3. 一个渗透自学者的自述
  4. 网友推荐2010年央视春晚节目单 恶搞社会热点
  5. MT【129】常数变易法
  6. pycharm找不到conda可执行文件
  7. 基于STM32开源项目:球上自平衡机器人
  8. 制作各种docker镜像
  9. xmapp无法启动Apache、Tomcat无法启动问题解决
  10. 使用接口测试活动的中奖概率(随机事件测试)