前面寫了一篇文章專門用來說HashMap的,確實HashMap在平時是很是經常使用的,可是其中所涉及的內容還遠遠不止這些,舉個例子:安全
HashMap<String,String> hashMap = new HashMap<>();
hashMap.put(1,"");//Error
複製代碼
首先咱們知道,定義了一個鍵值對類型都是String類型的HashMap,若是你往裏面丟入一個類型爲非String類型的鍵值對,那麼確定是會報錯的。可是若是把尖括號及裏面的內容去掉的話,程序是能夠經過編譯的。bash
HashMap hashMap = new HashMap<>();
hashMap.put(1,"");//Pass
複製代碼
那麼你會問,何苦要去掉括號呢?我明確的知道鍵值對的類型不是很方便嘛。確實,明確類型以後,編譯器能夠幫咱們檢查出不少插入數據類型不正確的問題,可是要知道泛型是在JDK1.5纔出現的,那麼在那個沒有泛型的年代,是怎麼確保類型安全的呢?ide
要知道,大多數的語言在最開始的時候都是沒有泛型的例如C#,Go(如今都不支持),Java。就拿前面例子中的hashMap來講,在JDK1.5以前,能夠在其中放入任何類型的數值。可是問題來了,若是咱們想構造一個只能傳入<String,String>類型的HashMap要怎麼作呢?能夠用相似裝飾器模式來實現,見代碼:ui
public class MyStringHashMapDecorator {
HashMap hashMap = new HashMap();
public void put(String key , String value){
hashMap.put(key,value);
}
public HashMap get(String key){
return (HashMap) hashMap.get(key);
}
}
複製代碼
可是問題來了,對於茫茫可能發生的狀況,按照這樣的話,我豈不是須要每一種都列出對應的狀態。因此在JDK1.5中推出了泛型,簡化了這些麻煩的操做,可是Java爲了向後兼容性,因此這種泛型只是在編譯期間存在的,運行期間仍是會經過類型擦除(Type Erasure),去掉泛型的。這一點能夠經過看字節碼能夠看出: spa
public static void main(String[] args) {
foo(new ArrayList<String>());//Error
}
public static void foo(ArrayList<Object> objects){
//do something
}
複製代碼
下面經過幾個例子來引出泛型的使用:
code
好比如今要比較兩個參數的大小,可是參數的類型不肯定,那麼就能夠用到泛型的綁定了。
舉例說明:cdn
public static void main(String[] args) {
System.out.println(max(1,2));//int
System.out.println(max(1.0,2.0));//double
System.out.println(max(1.0f,2.0f));//float
System.out.println(max(1L,2L));//long
System.out.println(max("abc","abd"));//long
}
private static <T extends Comparable<T>> T max(T a, T b) {
return a.compareTo(b) > 0 ? a : b;
}
複製代碼
結果以下:blog
2
2.0
2.0
2
abd
Process finished with exit code 0
複製代碼
可是在這就有疑問了:
1.爲何Comparable明明是個接口,卻要用extends關鍵字?
2.若是對兩種都實現了Comparable接口,可是對兩者類型不一樣的參數進行比較,會有什麼結果呢?
回答:
1.在泛型中,關鍵字extends後面既能夠跟類,也能夠跟接口。可是在實際意義上更接近因而綁定類型的自身或者子類型,因此用extends關鍵字更加接近。
2.見代碼: 繼承
public static void main(String[] args) {
//在ArrayList中指定了T的類型,第二個參數傳入的是T類型的父類型
sort(new ArrayList<Cat>(),new AnimalComparator());
}
private static <T> void sort(List<T> list, Comparator<? super T> c) {
list.sort(c);
}
}
class AnimalComparator implements Comparator<Animal> {
@Override
public int compare(Animal o1, Animal o2) {
return 0;
}
}
複製代碼