字母E和T分別代表元素和類型,但要注意它們不是由編譯器或類似的東西強制執行的。你幾乎可以放置任何東西,包括完整的單詞,但建議你使用單個大寫字母,因此最好區分它們(小寫字母看起來像變量名稱,以大寫字母開頭的單詞看起來像類,而全大寫單詞看起來像常量)
至於用法,就這樣想。當你創建一個數組時,你可以創建Object[]
,String[]
,Integer[]
,SomeClass[]
,它告訴你到底有什麼。在引入收藏/地圖類(List,Set,Map)的泛型之前,有一個問題是你可以在其中放置任何東西(有些人可能會認爲這不是問題)。所以現在你可以創建類似於數組的List<String>
,List<Object>
。雖然有一些差異。例如String[]
延伸Object[]
,但List<String>
不延伸List<Object>
所以你不能把一個字符串列表實例放在一個對象列表變量。
泛型的優點是你可以在任何類上擁有它們,而一個類可以有多個通用參數(如Map<K, V>
)。你可以把它看作給其他類的實例提供的參數Class
,告訴它們他們的方法應該接收或返回什麼類型。
是的,關鍵是編譯器可以檢查是否給他們正確的參數類型,以便避免出現在運行時的ClassCastExceptions。例如仿製藥之前,你可以這樣做:
String s = "";
List l = new ArrayList();
l.add(s);
Integer i = (Integer)l.get(0); // ClassCastException
但仿製藥:
String s = "";
List<String> l = new ArrayList<String>();
l.add(s);
Integer i = (Integer)l.get(0); // compiler warning: cannot cast from String to Integer
此外,你可以在一個單一的方法泛型類型參數就像在你的榜樣(類本身不需要有一個類型參數)。這告訴編譯器該方法必須匹配方法參數和/或返回類型的所有類型參數實例。在您的例子稱它想:
String[] a = new String[1];
List<Integer> l = new ArrayList<Integer>();
fromArrayToCollection(a, l);
會導致編譯錯誤,因爲該方法必須接受一個T[]
和Collection<T>
,T這裏是相同的。但你給了它一個String[]
(所以T這裏是字符串)和一個List<Integer>
(所以T這裏是Integer,而不是String)。如果我是List<String>
雖然,它會工作。 另請注意,List<T>
擴展了Collection<T>
,因爲List擴展了Collection,但即使T擴展S(無論T和S是什麼),List<T>
也不會擴展List<S>
。
哦,你可以在泛型指定的類限制的可以替代的類型放慢參數通配符:
public <T extends SomeClass> void fromArrayToCollection(T[] a, COllection<T> c);
這樣,如果你給它SomeClass的[]或SomeChildClass []的方法,將工作(其中SomeChildClass擴展了SomeClass),但不包含Object []或String []。
調用T是(只是)一個約定。如果你願意,你可以稱它爲Item(或FuzzyBear)。無論如何,它是該上下文中的「泛型類型」的佔位符(出現在<>的內部)。 – 2010-10-16 06:29:32
我知道,這只是一個例子,但爲此目的,有'Arrays.asList(T ...)'和'Collections.addAll(Collection,T ...)'。 – whiskeysierra 2010-10-16 09:13:37