前言
Java 5 添加了泛型,提供了編譯時類型安全檢測機制,該機制允許程序員在編譯時檢測到非法的類型。
泛型的本質是參數化類型,可以為以前處理通用對象的類和方法,指定具體的對象類型。聽起來有點抽象,所以我們將馬上看一些泛型用在集合上的例子:
泛型集合
先看一個沒有泛型的集合例子:
List list = new ArrayList();
list.add(new Integer(2));
list.add("a String");
因為 List 可以添加任何對象,所以從 List 中取出的對象時,因為不確定(List不記住元素類型)當時候保存進 List 的元素類型,這個對象的類型只能是 Object ,還必須由程序編寫者記住添加元素類型,然后取出時再進行強制類型轉換就,如下:
Integer integer = (Integer) list.get(0);
String string = (String) list.get(1);
通常,我們只使用帶有單一類型元素的集合,並且不希望其他類型的對象被添加到集合中,例如,只有 Integer 的 List ,不希望將 String 對象放進集合,並且也不想自己記住元素類型,並且強制類型轉換還可能會出現錯誤。
使用 Generics(泛型)就可以設置集合的類型,以限制可以將哪種對象插入集合中。 這可以確保集合中的元素,都是同一種已知類型的,因此取出數據的時候就不必進行強制類型轉換了,下面是一個 String 類型的 List 的使用例子:
List<String> strings = new ArrayList<String>();
strings.add("a String");
String aString = strings.get(0);
以上這個 List
Java 泛型從 Java 7 開始,編譯器可以自動類型判斷,可以省略構造器中的泛型,下面是一個Java 7 泛型例子:
List<String> strings = new ArrayList<>();
這也叫做菱形語法(<>), 在上面的示例中,實例化 ArrayList 的時候,編譯器根據前面 List
foreach 循環可以很好地與泛型集合整合,如下:
List<String> strings = new ArrayList<>();
// 這里省略將 String 元素添加進集合的代碼...
for(String aString : strings){
System.out.println(aString);
}
也可以使用泛型迭代器遍歷集合,如下:
List<String> list = new ArrayList<String>;
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
String aString = iterator.next();
}
注意,泛型類型檢查僅在編譯時存在。在運行時,可以使用反射或者其他方式使字符串集合插入其他對象,但一般不會這樣做。
當然泛型的用處不僅僅限於集合。
泛型類
從上面的內容中,我們已了解泛型的大概理念。
可以在自定義 Java 類上使用泛型,並不局限於 Java API 中的預定義類。定義泛型類只需要在類名后緊跟
public class GenericFactory<T> {
Class theClass = null;
public GenericFactory(Class theClass) {
this.theClass = theClass;
}
public T createInstance() throws Exception {
return (T) this.theClass.newInstance();
}
}
其中 Class.newInstance() 方法是反射知識的內容,這里只要知道此方法用於 theClass 類對象的創建就行。
GenericFactory<MyClass> factory = new GenericFactory<MyClass>(MyClass.class);
MyClass myClassInstance = factory.createInstance();
GenericFactory<SomeObject> factory1 = new GenericFactory<SomeObject>(SomeObject.class);
SomeObject someObjectInstance = factory1.createInstance();
使用泛型,我們就不必轉換從 factory.createInstance() 方法返回的對象,會自動返回 new GenericFactory
泛型方法
一個泛型方法定義如下:
public static <T> T addAndReturn(T element, Collection<T> collection){
collection.add(element);
return element;
}
其中 T 是方法返回值,
public T createInstance() throws Exception { ... }
這不是一個泛型方法,而是 GenericFactory
注意在泛型方法中,參數有 2 個,第一個是 T 類型的參數,第二個是元素類型為 T 的 Collection 集合,編譯器會根據實際參數來推斷 T 為何種類型 ,如下這樣是完全可行的:
String stringElement = "stringElement";
List<Object> objectList = new ArrayList<Object>();
Object theElement = addAndReturn(stringElement, objectList);
如上,第一個參數為 String 類型,第二個是 List