网站首页 > 精选教程 正文
原文
5.1.8 强制类型转换
第3章曾经讲过,将一个类型强制转换成另外一个类型的过程称为强制类型转换(casting)。Java 程序设计语言为强制类型转换提供了一种特殊的表示法。例如;
double x = 3.405;
int nx = (int) x;
将表达式 x的值转换成整数类型,舍弃了小数部分。
正像有时候需要将浮点数转换成整数一样,可能还需要将某个类的对象引用转换成另外个类的对象引用。再以混合有 Employee 和 Manager 对象的数组为例;
var staff = new Employee[3];
staff[0] = new Manager("(arl Cracker”,80000,1987,12,15);
staff[1] = new Employee("Harry Hacker",50000,1989,10,1);
staff(2] = new Employee("Tony Tester,40000,1990,3,15);
要完成对象引用的强制类型转换,转换语法与数值表达式的强制类型转换类似。用一对圆括号将目标类名括起来,并放置在需要转换的对象引用之前。例如;
Manager boss = (Manager) staff(0);
进行强制类型转换的唯一原因是:要在暂时忘记对象的实际类型之后使用对象的全部功能。例如,在ManagerTest 类中,staff 数组必须是 Eployee 对象的数组,因为它的一些元素是普通员工。我们需要将数组中引用经理的元素复原成 Manager 对象,从而能够访问它的所有新变量(需要注意,在第一节的示例代码中,为了避免强制类型转换,我们做了一些特别的处理。将 boss 变量存存入数组之前,先将它初始化为一个 Manager 对象。我需要正确的类型来设置经理的奖金)。
我们知道,在 Java 中,每个对象变量都有一个类型。类型描述了这个变量引用哪种对象以及它能做什么。例如,staff[i]引用一个 Eployee 对象(因此它还可以引用 Manager 对象)。
将一个值存入一个变量时,编译器将检查你是否承诺过多。如果将一个子类引用赋给一个超类变量,你的承诺较少,编译器是允许的。但将一个超类引用赋给一个子类变量时,就承诺过多了。必须进行强制类型转换,这样才能够通过运行时的检查。如果试图在继承链上进行向下的强制类型转换,并且“谎报”对象包含的内容,会发生什么情况呢?
Manager boss = (Manager) staff[1]; // ERROR
运行这个程序时,Java 运行时系统将注意到你的承诺不符,并产生一个 ClassCastException异常。如果没有捕获这个异常,那么程序就会终止。因此,应该养成这样一个良好的编程习惯:在进行强制类型转换之前,先查看是否能够成功地转换。为此只需要使用 instanceof 操作符。例如:
if (staff[i] instanceof Manager){
boss = (Manager) staff [ i ];
}
最后,如果这个类型转换不可能成功,那么编译器就不会让你完成这个转换。例如,下面这个强制类型转换:
String c = (String) staff[i];
将会产生编译错误,这是因为 String 不是 Employee 的子类
综上所述:
- 只能在继承层次结构内进行强制类型转换。
- 在将超类强制转换成子类之前,应该使用 instanceof 进行检查
注释:如果x为null,则进行以下测试
x instanceof C
不会产生异常,只是返回 false。这样处理是有道理的:因为 null 没有引用任何对象,当然也不会引用C类型的对象。
实际上,通过强制类型转换来转换对象的类型通常并不是一个好主意。在我们的示例中,大多数情况并不需要将 Employee 对象强制转换成 Manager 对象,两个类的对象都能够正确地调用 getSalary 方法,这是因为实现多态性的动态绑定机制能够自动地找到正确的方法。
只有在使用 Manager 中特有的方法时才需要进行强制类型转换,例如setBonus 方法。如果出于某种原因发现需要在 Employee 对象上调用 setBonus 方法,那么就应该自问超类的设计是否有问题。可能有必要重新设计超类,并添加一个setBonus 方法。请记住,一个未捕获的ClassCastException 异常就会导致程序终止。一般情况下,最好尽量少用强制类型转换和instanceof 操作符。
C++注释: Java 使用的强制类型转换语法来源于C语言“古老的过去”,但处理过程却有些像 C++的安全dynamic_cast 操作。例如,
Manager boss = (Manager) staff[i]; // Java
等价于
Manager* boss = dynamic_cast <Manager*>(staff[i]); // C++
它们之间只有一点重要的区别:当强制类型转换失败时,Java 不会生成null对象,而是抛出一个异常。从这个意义上讲,有点像 C++中的引用(reference) 转换。真是令人头疼。在 C++中,可以在一个操作中完成类型测试和类型转换。
Manager* boss = dynamic cast<Manager*>(staffi)); // C++
if (boss != NULL) ...
而在 Java 中,需要将 instanceof 操作符和强制类型转换结合起来使用:
if (staff[1] instanceof Manager)
Manager boss = (Manager) staff[i];
猜你喜欢
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 5.2.3相等测试与继承
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 5.2.4 hashCode方法
- 2024-11-28 Java入门书单
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 4.3.7 隐式参数与显式参数
- 2024-11-28 全网最完整的免费java教程讲义系列(四)——java的流程控制
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 4.6 对象构造 4.6.1重载
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 3.10 数组
- 2024-11-28 java 核心技术-12版 卷Ⅰ- 4.3 自定义类
- 2024-11-28 2019年Java核心技术我整理了200多页pdf,今天分享给你
- 2024-11-28 java 核心技术12版卷1 - 1.3 Java applet 与 Internet
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)