/** * Program : LearnPattern.java * Author : tanx * Create : 2013-5-10 下午4:22:46 * */package pattern;import java.util.ArrayList;import java.util.List;/** * * @author tanx * @version 1.0.0 * @2013-5-10 下午4:22:46 */public class LearnPattern<K, V> {// 推薦的命名規範是使用大寫的單個字母名稱作為型別參數。這與 C++ 約定有所不同(參閱 附錄 A:與 C++// 模板的比較),並反映了大多數泛型類將具有少量型別參數的假定。對於常見的泛型模式,推薦的名稱是://// K —— 鍵,比如映射的鍵。// V —— 值,比如 List 和 Set 的內容,或者 Map 中的值。// E —— 異常類。// T —— 泛型// Java 程式的型別安全。通過知道使用泛型定義的變數的類型限制,// tanx:顯示的約定,而不是存在於程式員的頭腦中,注釋裡,編譯器幫我們杜絕錯誤,而不是運行BUG// 消除原始碼中的許多強制類型轉換。這使得代碼更加可讀,並且減少了出錯機會。// 類型檢查從執行時挪到了編譯時間,這會提高可靠性並加快開發速度public void put(K key, V value) {//使用類定義的 相同的類型}public V get(K key) {//使用類定義的 相同的類型return null;}//限定傳入參數類型與傳回型別相同,沒在類定義泛型就要在方法名前加<T> ,T可以是其他字母public <T> T addTest(T value) { return null;}public void testCase1() {LearnPattern<Integer, String> bb = new LearnPattern<Integer, String>();bb.put(1, "test"); // 一定傳對參數String test = bb.get(1); // 無需類型轉換}public void testCase2() {List<Integer> intList = new ArrayList<Integer>();intList.add(2);// List<Number> numberList = intList; // 無法轉換 ,泛型不是協變的// numberList.add(2.0); // 如果能轉換,那麼這個2.0就能加,但實際intList不能加2.0List<?> numberList = intList; // 可以轉成 ? 時常用於升級代碼,消除轉換警告,但請注意下面// numberList.add(2);// ? 無法添加System.out.println(numberList.get(0));// ? 能做查詢numberList.clear();// ? 能做刪除}// 多個參數約束public <T> T ifThenElse(boolean b, T first, T second) {return b ? first : second;}public void testCase3() {String s = ifThenElse(false, "a", "b");Integer i = ifThenElse(false, new Integer(1), new Integer(2));// 非法,不僅僅是口頭約束,注釋,或者直接運行時出錯// String s = ifThenElse(b, "pi", new Float(3.14));}// 限制類型 //明白無誤告訴別人,這個類裡面屬性test只能為Number子類public class testCase4<T extends Number> {private T test;}interface Collection<V> {boolean addAll(Collection<? extends V> c); // 不改變原來的語義,可添加集合及子類集合boolean removeAll(Collection<?> c); // 刪除混合的集合類}// class Enum<E extends Enum<E>>// 型別參數 E 用於 Enum 的各種方法中,比如 compareTo() 或 getDeclaringClass()。// 為了這些方法的型別安全,Enum 類必須在枚舉的類上泛型化。//// Enum<E> 這個是它本身 , E extends Enum<E> 表示是它本身的子類型// 因為枚舉類實現了implements Comparable<E> ,有如下方法:// public final int compareTo(E o) {// Enum other = (Enum)o;// Enum self = this;// if (self.getClass() != other.getClass() && // optimization// self.getDeclaringClass() != other.getDeclaringClass())// throw new ClassCastException();// return self.ordinal - other.ordinal;// }// public final Class<E> getDeclaringClass() {// Class clazz = getClass();// Class zuper = clazz.getSuperclass();// return (zuper == Enum.class) ? clazz : zuper;// }//API解釋//public final Class<E> getDeclaringClass()//返回與此枚舉常量的枚舉類型相對應的 Class 對象。// 若且唯若 e1.getDeclaringClass() == e2.getDeclaringClass() 時,// 兩個枚舉常量 e1 和 e2 的枚舉類型才相同。(由該方法返回的值不同於由 Object.getClass() // 方法返回的值,Object.getClass() 方法用於帶有特定常量的類主體的枚舉常量。)//返回://與此枚舉常量的枚舉類型相對應的 Class 對象// public native Class<? super T> getSuperclass(); //Class的本地方法,返回該類的父類型public Class<? super Integer> testCase5() { // 返回Integer的父類類型return null;}//特殊效果示範abstract class Foo <T extends Foo<T>>{public abstract T subclassAwareDeepCopy();}class Bar extends Foo<Bar> { public Bar subclassAwareDeepCopy() { Bar b = new Bar(); // ... return b; } }public class testCase5<T extends Number> {Bar b = new Bar(); Foo<Bar> f = b; // 子類和父類相互賦值 Bar bb2 = b.subclassAwareDeepCopy(); Bar bb3 = f.subclassAwareDeepCopy(); // 父類直接返回子類的執行個體,而且不用Cast Bar1 b1 = new Bar1();Foo1<Foo1> f1 = b1; // 子類和父類相互賦值 Bar1 b12 = b1.subclassAwareDeepCopy(); Bar1 b13 = (Bar1)f1.subclassAwareDeepCopy(); // 父類返回子類的執行個體,需要Cast Bar2 b2 = new Bar2(); Foo2 f2 = b2; // 子類和父類相互賦值 Bar2 b22 = b2.subclassAwareDeepCopy(); Bar2 b23 = (Bar2)f2.subclassAwareDeepCopy(); // 父類返回子類的執行個體,需要Cast }//對比1 -----------------------------------------------------------------------abstract class Foo1<T> {public abstract T subclassAwareDeepCopy();}//這裡因為沒有約束,所以我們可以隨意填,你可能認為這填Bar1就不用轉型了,//但那隻存在於我們腦海中,如果是給別人提供api介面,顯然要用 <T extends Foo<T>>class Bar1 extends Foo1<Foo1> { public Bar1 subclassAwareDeepCopy() { Bar1 b = new Bar1(); // ... return b; } }//對比2 -----------------------------------------------------------------------abstract class Foo2 {public abstract Foo2 subclassAwareDeepCopy();}class Bar2 extends Foo2 { public Bar2 subclassAwareDeepCopy() { Bar2 b = new Bar2(); // ... return b; } }}