Java 容器 & 泛型:六、容器講到為什么要使用泛型
Writer:BYSocket(泥沙磚瓦漿木匠)
微博:BYSocket
豆瓣:BYSocket
ArrayList是集合類中無處不在的,泛型也是,泛型對集合類尤其有用。但是為啥要使用泛型?理解好了這個問題可以幫助理解相關的更多知識點。下面泥瓦匠以最簡單的例子來驗證這個問題。
一、泛型
泛型的目的是為了可以讓更多不同類型的對象重用。沒錯,這樣理解就太low。真正目的是為了在編譯時找到bug,而不是在運行時。(編譯時,指的是源代碼翻譯成機器識別的代碼的時候。運行時,是指代碼在機器中運行的時候。)泛型只存在編譯時,理解這個可以幫助你更好的理解泛型。
這樣,在編譯時會比在運行時更容易地找到bug和修復。
二、實現沒有泛型的簡易版ArrayList
簡易版的ArrList有個Obejct對象(因為是Object,我們可以add任意類型。)比如說,Integer 和 String的。代碼如下:
package javaBasic.generic;/**
簡易版ArrayList */ class ArrList { private Object obj;
public Object getObj() {
return obj;
}
public void add(Object obj) {
this.obj = obj;
}
}
public class TestArrayList { public static void main(String[] args) { ArrList arrList = new ArrList(); arrList.add(1); arrList.add("1");
Integer objInt = (Integer) arrList.getObj();
System.out.println(objInt);
}
}</pre>
運行可以看出會出現ClassCastException:
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer at javaBasic.generic.TestArrayList.main(TestArrayList.java:30)
想問的問題是:”這Object對象屬性,怎么不能強轉呢?“
答:編譯時,代碼沒錯的。運行main時,當set了String類型時,將結果強制轉換為Integer就會報錯這個錯了。
泥瓦匠的記憶宮殿又來了:
1、使用泛型比那些雜亂的需要強制轉換的Object代碼具有更好的安全性和可讀性。
2、使用泛型可以在編譯時輕松找到和解決bugs
三、使用改寫簡易版ArrayList
使用泛型代碼如下:
package javaBasic.generic;/**
簡易版ArrayList */ class ArrList<T> { private T obj;
public T getObj() {
return obj;
}
public void add(T obj) {
this.obj = obj;
}
}
public class TestArrayList { public static void main(String[] args) { ArrList<Integer> arrList = new ArrList<>(); arrList.add(1); // arrList.add("1");
Integer objInt = arrList.getObj();
System.out.println(objInt);
}
}</pre>
這時候如果想用
arrList.add("1");
會發現:
這時候就是泛型大顯身手的時候,也不用需要對屬性 get 方法時的強制轉換。其實, Java 泛型只是編譯時的概念,因為編譯后類型會被擦除,還原本真。這里T就相當于Integer。
四、小結
泥瓦匠記憶宮殿:
1、在編譯時檢查強類型
2、顯示轉換的消除(上面的Integer get省去)
3、更好地實現代碼重用和泛型算法
4、使用泛型比那些雜亂的需要強制轉換的Object代碼具有更好的安全性和可讀性。
Java 泛型只是編譯時的概念,因為編譯后類型會被擦除,還原本真。哈哈~下次說這個。
Writer:BYSocket(泥沙磚瓦漿木匠)