缩小和扩大对象引用
转换一个基类的实例,以一个子类,如:b = (B) a;
被称为缩小 (因为你是努力缩小的基类对象,以更具体的类对象),需要一个明确的类型转换。
将子类的实例强制转换为基类,如:A a = b;
,称为扩展,不需要类型转换。
为了说明,请考虑以下类声明和测试代码:
class Vehicle {
}
class Car extends Vehicle {
}
class Truck extends Vehicle {
}
class MotorCycle extends Vehicle {
}
class Test {
public static void main(String[] args) {
Vehicle vehicle = new Car();
Car car = new Car();
vehicle = car; // is valid, no cast needed
Car c = vehicle // not valid
Car c = (Car) vehicle; //valid
}
}
语句 Vehicle vehicle = new Car();
是一个有效的 Java 语句。Car
的每个实例也都是 Vehicle
。因此,赋值是合法的,无需显式类型转换。
另一方面,Car c = vehicle;
无效。vehicle
变量的静态类型是 Vehicle
,这意味着它可以参考 Car
,Truck,
MotorCycle, or any other current or future subclass of
Vehicle. (Or indeed, an instance of
Vehicleitself, since we did not declare it as an
abstractclass.) The assignment cannot be allowed, since that might lead to
carreferring to a
Truck`实例的实例。
为了防止出现这种情况,我们需要添加一个显式的类型转换:
Car c = (Car) vehicle;
类型转换告诉编译器我们期望 vehicle
的值是 Car
或 Car
的子类。如有必要,编译器将插入代码以执行运行时类型检查。如果检查失败,则在执行代码时将抛出 ClassCastException
。
请注意,并非所有类型转换都有效。例如:
String s = (String) vehicle; // not valid
Java 编译器知道与 Vehicle
类型兼容的实例永远不能与 String
类型兼容。类型转换可能永远不会成功,并且 JLS 强制要求编译错误。