Java语言对象引用的缩小和扩大

示例

如:中将基类的实例强制转换为子类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; // 有效,不需要强制转换

        Car c = vehicle // 无效
        Car c = (Car) vehicle; //valid
    }
}

该语句是有效的Java语句。的每个实例也是。因此,该分配是合法的,不需要显式的类型转换。Vehicle vehicle = new Car();CarVehicle

另一方面,Car c = vehicle;是无效的。vehicle变量的静态类型表示该变量Vehicle可以引用的实例Car卡车,摩托车, or any other current or future subclass of车辆. (Or indeed, an instance of车辆itself, since we did not declare it as an抽象class.) The assignment cannot be allowed, since that might lead to汽车referring to a卡车实例。

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

Car c = (Car) vehicle;

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

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

String s = (String) vehicle;  // 无效

Java编译器知道与类型兼容的实例Vehicle 永远不会与类型兼容String。类型转换永远不会成功,而JLS要求这样做会导致编译错误。