縮小和擴大物件引用

轉換一個基類的例項,以一個子類,如: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 強制要求編譯錯誤。