---------------------- ASP.Net+Android+IOS開發、.Net培訓、期待與您交流! ----------------------
jdk1.5加入了泛型這一概念。
泛型:用於解決安全問題,是一個安全機制。
好處:
1.把原本的運行時會出現的類型轉換異常(ClassCastException),轉移到程序編譯時期,方便程序員解決問題,讓運行時期的問題減少,提高程序的安全性。
2.避免了強制類型轉換的麻煩。
3.實現模板設計模式
通過一個例子瞭解泛型:
這個程序中向集合中添加數據,前三個添加的是字符串,最後一個添加的是整數。
編譯時並不會出現問題,但是運行時會出現類型轉換異常。
使用泛型:
使用泛型,把集合所存儲的數據類型事先規定好。所以在程序中如果有其他類型的數據,編譯就不會通過。
不過在實驗中我發現,現在的java版本已經會自動把整數轉換爲字符串,所以如果使用的jdk版本高的話,在集合中存入整數可能不會出現問題。
但是通過另一中途徑一定可以發現問題。
在這個程序中我直接存了一個對象到集合中,編譯也不會出錯,不過運行時出現了類型轉換異常(java.lang.ClassCastException)。
這樣,使用泛型的好處就一目瞭然了。程序員不注意可能會在存放字符串的集合中存入整數,編譯時可能不會出現問題,一位程序可以用了就完事了,但是運行時會出現問題。如果存數據的動作由用戶完成,程序員沒有提供數據類型這個問題,用戶在使用是出現了問題,那就麻煩了。
通過上面的列子可以看到泛型的作用。
那麼,java中什麼時候使用泛型呢?
通常在集合框架中很常見,因爲集合是存放對象的,不想數組那樣,在定義一個數組時就把數組的長度,類型都定義好了,集合都沒有定義,所以使用泛型可以規定集合存放的數據類型。
通過查看Collection接口的API文檔可以發現:
接口 Collection<E>
方法摘要 | |
---|---|
boolean |
add(E e)
確保此 collection 包含指定的元素(可選操作)。 |
注意Collection後面的<E>就是使用泛型,而在add()方法中,參數也規定爲(E e)。
到這裏基本可以理解反省的使用方法了,拿集合來說:
<>是泛型的標誌,<>裏面的內容是要存入集合的數據的類型,把類型以參數的方式傳遞給集合類。
泛型在比較器中也用到。
java.util
接口 Comparator<T>
- 類型參數:
T
- 此 Comparator 可以比較的對象類型
方法摘要 | |
---|---|
int |
compare(T o1,
T o2) 比較用來排序的兩個參數。 |
舉個例子來看看 Comparator接口所使用到的泛型。
按照字符串的長度進行比較。
Comparator接口可以比較不同對象的同一屬性,比如比較兩個學生的年齡大小,但是不能比較一個學生的年齡和另一個學生的姓名的大小。
這也可以理解爲什麼Comparator接口要用到泛型。
自己也可以寫泛型類,模仿集合接口使用泛型的方法即可。
泛型也稱爲模板或參數多肽,既是模板,就應該有模板的特性,下面通過自己我寫的一個泛型類來體現泛型的模板特性。
通過程序可以看到,utils類爲泛型類,在utils類中定義了show()方法,參數爲T類型。
main()方法中既可以傳遞字符串參數給show()方法,也可以傳遞Integer參數給show()方法,這樣就不用分別爲字符串和整型參數寫不同的show()方法,這就體現出了模板的特性。
而且當給泛型類傳遞了數據類型參數後,就規定了泛型類對象所能接受的參數類型,如果傳遞的參數類型爲其他類型,則編譯不會通過,而不用泛型,編譯時可以通過的。
因爲在確定了數據類型爲String類型後,又傳遞了整型和Object類型的參數,所以編譯不通過。
這就體現了泛型的安全性特點。
除了定義泛型類,還可以定義泛型方法,反省方法的操作性更靈活,因爲定義泛型類的話,整個類裏面的方法接收的參數類型都是一致的,而定義泛型方法,則方法可以接收不同類型的數據。
泛型方法的定義格式:
public <T> void show(T t)
{
System.out.println(t);
}
使用時給改方法傳遞任何類型的參數都可以。
那麼,可以在泛型類中再定義泛型方法嗎?
會出錯嗎?
哪個優先級更高?
猜是猜不出來的,試試就知道了。
定義泛型方法時,參數類型<T>應該放在返回類型符前面,修飾符後面。
public static <T> void show(T t){ } ;
再看下面一個例子:
Student類繼承Person類,把Person對象和Student對象分別存入集合中,然後調用泛型方法printAll()打印。
如果使用反省方法打印的話,那麼任意類型的對象都可以打印。
而如果只想讓繼承Person類的對象纔可以使用打印方法打印,那些非Person繼承類的對象不能打印,能否實現呢?答案是能。
這就要用到泛型限定。
語法是這樣的:
ArrayList<? extends Person>
?是通配符,參數不是單單一個了,而是一個繼承語句。
當給泛型方法printAll()傳遞非Person()子類對象作爲參數是,編譯就會報錯,就不能使用該泛型方法。
這就完成了泛型限定,只有Person子類的對象纔可以使用此泛型方法。
反省最重要的兩個特點:
1. 安全
2. 模板
記住這兩個特點,再去學習泛型就明白,所有泛型的使用都是爲了實現這兩個特性。
---------------------- ASP.Net+Android+IOS開發、.Net培訓、期待與您交流!
----------------------
詳細請查看 www.itheima.com