# Java - Generics的一些細節 ###### tags: `Java` `Basic Java` ## 1. 通用符號:? 假設現在要設計一款汽車比賽,並且包含Benz跟BMW這兩個品牌的汽車 依照正常設計邏輯,我們需要設計一個Car的類別、再分別設計Benz與BMW兩個子類去繼承Car ``` class Car{ } class Benz extends Car { } class BMW extends Car { } ``` 然後為了存取資料方便,我們使用ArrayList進行數據存取 並設計一個共用方法讓兩個類別都可以使用 結果發現出現編譯錯誤了 ``` public class Demo { public static void main(String[] args) { ArrayList<Benz> benz = new ArrayList<>(); benz.add(new Benz()); benz.add(new Benz()); benz.add(new Benz()); go(benz); -> Compiling Error!!! ArrayList<BMW> bmws = new ArrayList<>(); bmws.add(new BMW()); bmws.add(new BMW()); bmws.add(new BMW()); go(bmws); -> Compiling Error!!! } public static void go(ArrayList<Car> Cars) { } } ``` 出現編譯錯誤的原因: **Java認為 ArrayList<Benz>/ArrayList<BMW> 跟ArrayList6<Car>是兩個不一樣的東西,所以沒辦法當成參數進行傳入** 此時解法就是使用**?**這個通用符號來當作類型 ``` public static void go(ArrayList<?> Cars) { } ``` 但假設今天原本的需求中新增了一個Dog類別,用同樣的ArrayList裝進Dog object之後,卻發現Dog也可以使用這個共用方法了。 雖然編譯沒有出現錯誤,但是整個設計邏輯卻出現了錯誤 ``` class Dog{ } --- ArrayList<Dog> dogs = new ArrayList<>(); dogs.add(new Dog()); dogs.add(new Dog()); dogs.add(new Dog()); go(dogs); -> No comiling error but STRANGE!! ``` 針對這個問題,我們就要使用Bounded Type Parameters來解決 **? extends 父類別** 代表參數只能傳入繼承該父類別的子類別 ``` public static void go(ArrayList<? extends Car> Cars) { } ``` 此時 go(dogs);這一行程式就會出現錯誤 另外有個? super 子類別的用法,但比較少用