缩小和扩大对象引用

转换一个基类的实例,以一个子类,如: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 ofVehicle. (Or indeed, an instance ofVehicleitself, since we did not declare it as anabstractclass.) The assignment cannot be allowed, since that might lead tocarreferring to aTruck`实例的实例。

为了防止出现这种情况,我们需要添加一个显式的类型转换:

Car c = (Car) vehicle;

类型转换告诉编译器我们期望 vehicle 的值是 CarCar 的子类。如有必要,编译器将插入代码以执行运行时类型检查。如果检查失败,则在执行代码时将抛出 ClassCastException

请注意,并非所有类型转换都有效。例如:

String s = (String) vehicle;  // not valid

Java 编译器知道与 Vehicle 类型兼容的实例永远不能String 类型兼容。类型转换可能永远不会成功,并且 JLS 强制要求编译错误。