public class Test {
public static void main(String[] args) {
ArrayList<XiaoMi> xiaoMiList = new ArrayList<XiaoMi>();
ArrayList<BYD> bydList = new ArrayList<BYD>();
run(xiaoMiList); //錯誤使用
}
public static void run(ArrayList<Car> list) {
// 汽車跑的邏輯
System.out.println("the car runs fast");
}
}
疑問:xiaoMiList中的每個元素都是Car的子類,為什麼不能使用多型的方式實現將ArrayList
傳給ArrayList 呢
java中的協變
在Java中,協變是指一個型別的子型別可以被當作其父型別來使用。例如,如果 XiaoMi 是 Car 的子類,那麼 XiaoMi 的物件可以被當作 Car 的物件來使用。這是Java語言設計中的一項重要特性,它支援物件導向程式設計中的多型性。
陣列列表與協變
然而,儘管Java中的基本型別和引用型別支援協變,ArrayList 卻不支援協變。這是因為 ArrayList 的設計考慮到了型別安全性和避免潛在的執行時錯誤。
設計思想
Java中泛型擦除
1. 型別安全性:
Java的設計目標之一是保證型別安全性。如果 ArrayList<XiaoMi> 能夠被當作 ArrayList<Car> 使用,那麼可能會發生以下情況:
* 可能意外地向 ArrayList<XiaoMi> 中新增了一個 BYD 物件,因為 BYD 也是 Car 的子類。
* 這種操作在編譯時是合法的,但在執行時會導致 ClassCastException,因為 ArrayList<XiaoMi> 實際上只能儲存 XiaoMi 物件。
2. 泛型擦除:
Java中的泛型是基於型別擦除實現的。這意味著在編譯時型別引數被替換為其實現的原始型別(例如 ArrayList<XiaoMi> 在執行時實際上就是 ArrayList<Object>),而在執行時型別引數的資訊被丟棄。
如果 ArrayList<XiaoMi> 能夠被當作 ArrayList<Car> 使用,那麼編譯器無法保證型別安全,因為它不知道 XiaoMi 是否是 Car 的子類。