繼上一文《java泛型的學習筆記[1]—基礎知識》之後,本文將介紹泛型的一些應用和應用過程中遇到的問題。
在此之前,我們先給出一張類圖:
1)泛型類型的子類型問題
我們首先來看這樣一句代碼。該行代碼正確,因爲Cat是Animal的子類型
Animal animal=new Cat();//
但是再看下一句代碼:
AarrayList<Animal> animals=new ArrayList<Cat>();//編譯出錯
這句代碼編譯出錯,因爲雖然因爲Cat是Animal的子類型,但是: ArrayList<Cat>不是AarrayList<Animal>的子類型。
如果深究起來,只能說ArrayList<Cat>是List<Cat>的子類型。而ArrayList<Cat>與AarrayList<Animal>是兩個不兼容的類型,或者說是兩個沒有關係的類型。
2)通配符的使用問題
我們先來看看兩段編譯出錯的代碼。其
1.ArrayList<?> list=new ArrayList<Cat>();
list.add(new Cat());//編譯出錯
2.ArrayList<? extends Animal> list=new ArrayList<Cat>();
list.add(new Cat());//編譯出錯
出錯的原因或許大家能想明白:使用了"?"或者"? extends Animal"的通配符,我們不確定“?”代表的類型。比如ArrayList<? extends Animal>,通配符可能代表的類型包括:Animal,Cat或Dog,還有SmallCat。若是“?”表示Dog,而這裏的list.add(new Cat())肯定會出錯,即?表示的類型與你想要添加數據的類型,可能是不兼容的。對於ArrayList<?>,其實也相當於ArrayList<? extends Object>。所以1 和2 用法本質上是相同的。
因此,爲了消除不確定性,爲了確保類型安全,對於使用"? extends"通配符的數據結構,都不允許往其中添加任何的值了。
那麼對於“? super ”類型的情況呢?
比如:
ArrayList<? super Cat> list=new ArrayList<Cat>();
list.add(new Cat());//
list.add(new SmallCat());//
以上三句代碼就是正確的。
爲什麼會這樣呢?原理其實不難:因爲使用了"? super Cat"後,雖然“?”也充滿了不確定性,包括:Cat,Animal,還有Object。但是其中卻有一條確定性:Cat與SmallCat一定與?兼容。因爲?可能的最底層次就是Cat,也就是說Cat和SmallCat一定是?本身的類型或?的子類型。這時,list.add(new Cat());與list.add(new SmallCat());當然是是能保證正確的。
3)泛型在SSH框架中的運用
在ssh中,一般我們會自定義一些基類,對我們項目中的一些功能或代碼進行封裝。比如,我們通常會定義Dao層的基類,Service層的基類,還有Action的基類 等
等。
以DAO層爲例,在做項目的時候每次都爲每個POJO實體寫一個對應的DAO很麻煩,雖然可以由IDE或者一些快速生成工具來生成,但是也難免需要更改。基於此
原因,一般我們需要定義一個通用的泛型DAO來封裝一些最基本的操作,包括對實體的增刪改查等。這樣就大大簡化了代碼,也保證了DAO層在使用時的類型安全。
OK,本文就到這裏吧。歡迎各位參與討論和補充內容。