(一)

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

/**

* @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

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

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

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

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

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

  2. java递归url目录_Java递归实现某个目录下所有文件和目录

    import java.io.File; import java.util.ArrayList; public class Test1// 实现打印某个目录下的所有文件和目录,要目录在上,文件在下,每 ...

  3. java src 文件路径_java中获得src路径下文件的常用方法

    在代码中一般读取src下的配置文件 读取src路径下的log4j.properties和message.properties 读取message.properties文件并将properties中的键 ...

  4. mongodb java id 查询数据_java 用 _id 查找 MongoDB 下的数据

    找网上的资料看了下增删改查,等日后补上. 已经实现了数据的插入,现在想通过 _id属性来查找数据.一开始看到 类似 55b321df715cc162076eb466 这么一长串的内容觉得是string ...

  5. java向上和向下的区别_Java的向上和向下转型

    在Java编程中经常碰到类型转换,对象类型转换主要包括向上转型和向下转型. 向上转型 我们在现实中常常这样说:这个人会唱歌.在这里,我们并不关心这个人是黑人还是白人,是成人还是小孩,也就是说我们更倾向 ...

  6. java 文件夹下的文件_java读取某个文件夹下的所有文件

    import java.io.FileNotFoundException; import java.io.IOException; import java.io.File; public class  ...

  7. java 向下转型运行时错误_Java向上转型和向下转型

    首先定义父类Animal,所有动物都有一个吃东西的方法:子类Dog还增加了一个叫的功能. public classAnimal {public voideat() { System.out.print ...

  8. java 创建目录及文件_java中如何在系统目录下创建文件夹和文件

    我来解释一下吧,我不知道你的水平,所以可能讲的比较罗嗦了点,希望你能有所收获: 1 java程序的运行原理和编译执行一个java程序的步骤: java程序是通过java虚拟机解释,将其中的代码(字节码 ...

  9. java 文件夹目录_java如何取得文件夹下所有的子目录

    展开全部 package edu.chinasoft.wtf; import java.io.File; /** * @author :wtf * @version 创建时间:2018年3月5日 上午 ...

最新文章

  1. svn的代码提交到git服务器_svn服务器代码仓库,数据迁移到git仓库
  2. boot idea无法识别spring_intellij idea springboot无法读取配置文件的解决方法
  3. 设置开机时自动开启和关闭的软件
  4. 判断数据是否服从某一分布(二)——简单易用fitdistrplus包
  5. Machine Learning - Andrew Ng on Coursera (Week 4)
  6. leetcode 424. 替换后的最长重复字符(滑动窗口)
  7. tb项目管理实践_项目经理与项目管理整理
  8. bzoj 2245 [SDOI2011]工作安排【最小费用最大流】
  9. python 控件类多个实例_Python笔记_第四篇_高阶编程_GUI编程之Tkinter_2.控件类
  10. 字节码指令之方法调用与返回指令
  11. run.gps+trainer+uv+for+android,android 2.1(三星spica i5700)上的蓝牙问题配对工作但连接不起作用...
  12. 30 行代码实现蚂蚁森林自动收能量(附源码)
  13. JavaScript加法运算
  14. 2021-09-27 网安实验-文件恢复-DiskGenius恢复已删除文件
  15. 快手如何运营才能快速涨粉?
  16. 乓乓响再度冲刺港股:来自临时及应急服务客户毛利率达70%
  17. 产品经理如何做好需求调研
  18. 蓄水池问题c语言编程,蓄水池算法(Reservoir Sampling)
  19. 在docker容器中操作es,并给es7.6添加用户鉴权设置密码
  20. bp神经网络和cnn神经网络,RNN神经网络适用于什么

热门文章

  1. 重学 Java 设计模式:实战建造者模式「各项装修物料组合套餐选配场景」
  2. 实战演示:使用Python编写人脸识别测试代码,让你的应用拥有智能感知能力
  3. vb屏幕分辨率设置和获取_hawkol_新浪博客
  4. 树莓派 LCD驱动安装,及屏幕分辨率设置
  5. 怎样找回恢复手机删除照片
  6. FPGA 及数字电路基础小知识(二)
  7. Android项目:手机安全卫士(13)—— 通讯卫士之电话拦截与挂断
  8. ie中的html分页控制,用IE打印网页表格,实现自动分页、每页加表头
  9. 天猫魔盒1S:电视购物新体验
  10. 企业如何做好知识文档管理?