Effective Java Item29 - 優先考慮泛型
December 09, 2018
這篇是Effective Java - Favor generic type章節的讀書筆記 本篇的程式碼來自於原書內容
Item29: 優先考慮泛型
一般來說 將集合聲明參數化 或是使用library提供的泛型方法 不會太困難 但要自己編寫泛型就需要多加練習
本篇會實際走過一個完整的泛型化的步驟 讓你知道怎麼讓一個類別實現泛型
Stack實現
看一下我們在Item7看到的Stack
你看到 elements是個物件數組 這就是個練習泛型的好目標
第一步: 給聲明添加類型參數
先在Stack
後面加上<E>
然後把所有類別裡面的Object
換成E
通常第一部做完 會看到不少錯誤 幸運的是這次只有一個
第二步: 消除錯誤
原因是你不能創建一個不能具體化的Array 編譯器根本不知道E是什麼
對於這種問題 有兩種主要的解決方法
解法1
創一個Object Array 後再強制轉型
寫完後 從錯誤變成警告
編譯器無法證明這個轉換是typesafe 但是我們可以 原因如下
1.可能會產生問題的elements
是private 永遠不會傳給客戶
2.會寫進elements
的唯一方法是push
而push
的傳入參數是E
所以我們可以確定 這個強制Cast很安全 所以我們可以加上註解來抑制警告
別忘了當你要抑制警告時 盡可能縮小範圍
解法2
把elements
從E[]
變成Object[]
既然elements是Object[]
那constructor裡就沒問題了 問題在pop
一樣我們強制轉型(E)
看到了警告
抑制它
兩種解法比較
兩種解法都有追隨者 第一種明確的定義elements
是E[]
而且只需要在constructor中處理好就可以
但第二種 因為elements
是Object[]
所以在每次讀取的時候 你都必須要Cast
下面的程式展示了如何使用我們的泛型Stack
Stack<E>
裡面的E
可以是任何東西 Stack <Object>
Stack <int []>
Stack <List <String >>
但不能是primitive type 比如說Stack<int>
Stack<long>
你只能用Stack<Integer>
或Stack<Long>
代替
結論
使用泛型 比使用強制轉換更安全 當你手上有一些現有的類型應該要被泛型化 像是本文一開始的Stack 就試著把它泛型化
這會讓這類型的新用戶覺得易於使用 而且不會破壞現有的客戶端