在多态的情况下,由于对象以其父类的身份出现,对子类中新添加成员的访问受到限制,有时我们可能又需要恢复一个对象的本来面目——造型(Casting),以发挥其全部潜力。让我们结合一个具体的例子来介绍对象造型。
例6-14 对象造型举例
源文件:Person.java
public class Person{
private String name;
private int age;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
public String getInfo(){
return "Name: " + name + "tAge: " + age;
}
}
源文件:Student.java
public class Student extends Person{
private String school;
public void setSchool(String school){
this.school = school;
}
public String getSchool(){
return school;
}
}
源文件:Test.java
public class Test{
public void cast(Person p){
//System.out.println(p.getSchool()); //非法,编译出错!
Student stu = (Student)p; //p1
System.out.println(stu.getSchool());
}
public static void main(String[] args){
Test t = new Test();
Student s = new Student();
s.setSchool("THU");
t.cast(s);
}
}
程序运行输出结果为:
THU
本次程序运行中,实参s所引用的实际上是子类Student的对象,该子类中确实封装了功能方法getSchool(),但是由于cast()方法中形参p声明为Person类型,因此不能通过变量p直接访问getSchool()方法。但是通过造型将Person类型变量p的值赋给新声明的Student类型变量stu之后,通过变量stu就可以直接访问getSchool()方法了。
实际上,所谓的造型其实就是引用类型数据值之间的强制类型转换,为更好地说明造型操作的实现细节,特给出相应的内存状态如图6-4所示。

图6-4 程序运行到p1处的内存状态
从上图中可以看出,造型操作只是将父类类型引用变量的值直接赋给声明为子类类型的变量,但并不是随便什么类型的数据之间都可以进行造型,Java语言中造型的具体规则如下:
从子类到父类的类型转换可以自动进行;
在多态的情况下,从父类到子类的类型转换必须通过造型(强制类型转换)实现;
无继承关系的引用类型间的转换是非法的。
例如由于String类和Person类之间没有继承关系,因此下述语句是非法的:
String s = "Hello,World!";
Person p = (Person)s; //编译出错
事实上,此时引用变量s所引用的String类对象中根本不可能封装Person类中定义的name、age等属性,因此也就无法将一个String对象替代Person类型对象来使用。
基于类似的原因,从父类到子类的造型也不是都能成功——只有当对象的真正类型本就是子类类型,只是在多态的情况下,被一个声明为父类类型的变量所引用,才可以进行造型处理,即再恢复该对象的本来面目。而一个对象如果其真正类型就是父类类型,是不能被造型为子类类型的,假定Student类仍然继承了Person类,则下述代码虽能通过编译,但运行时会出错:
Person p = new Person();
Student stu = (Student)p; //运行出错
相关错误信息为:java.lang.ClassCastException: Person cannot be cast to Student
关于造型的合法性检查是分两个阶段进行的:
编译时只检查造型操作所涉及的两种类型间是否存在继承关系,有则通过编译,否则报错;
运行时再检查该时刻对象真正的类型是否确为造型的目标类型或其子类类型,是则通过,否则运行出错。
版权说明:
本文摘自北京新科海学校-v512工作室(张利国、刘伟老师)编著《JavaSE应用程序设计》一书,版权所有,转载请注明出处。
相关课程:JAVA软件工程师就业班————7月13日开课