《Java 核心技术卷1 第10版》学习笔记 ------ 泛型【基础】
泛型從Java SE 5.0 中開始出現,是 Java 程序設計語言從 1.0 版本發布以來,變化最大的部分。
使用泛型機制編寫的程序代碼要比那些雜亂地使用 Object 變量,然后再進行強制類型轉換的代碼具有更好的安全性和可讀性。特別的泛型對集合類尤其有用,例如,ArrayList 就是一個無處不在的集合類。
至少在表面上看來, 泛型很像 C++ 中的模板(template)。
8.1 為什么要使用泛型程序設計
泛型程序設計(Generic programming) 意味著編寫的代碼可以被很多不同類型的對象所重用。
8.1.1 類型參數的好處
在 Java 中增加范型類之前, 泛型程序設計是用繼承實現的。ArrayList 類只維護一個 Object 引用的數組:
public class ArrayList // before generic classes {private Object[] elementData;...public get Object get(int i){...}public get Object add(Object o){...} }這種方法有兩個問題。
// 當獲取一個值時必須進行強制類型轉換。 ArrayList files = new ArrayList(); ... String filename = (String) files.get(0);// 此外,這里沒有錯誤檢査。可以向數組列表中添加任何類的對象。 files,add(new File(". .."));對于這個調用,編譯和運行都不會出錯。然而在其他地方,如果將 get 的結果強制類型轉換為 String 類型, 就會產生一個錯誤。
泛型提供了一個更好的解決方案: 類型參數( type parameters)。ArrayList 類有一個類型參數用來指示元素的類型:
// 泛型類使用類型參數,指明存儲的數據類型 // 這使得代碼具有更好的可讀性。人們一看就知道這個數組列表中包含的是 String 對象。 ArrayList<String> files = new ArrayList<String>():// Java SE 7 之后可以這樣寫, 略去后面的泛型說明 ArrayList<String> files = new ArrayList();使用泛型指定明確類型之后,編譯器可以更好的檢測,從而降低出現類型轉換異常的可能,故更加安全。
8.1.2 誰想成為泛型程序員
應用程序員【做實際應用開發的程序員,非專業造輪子】往往更喜歡使用現成的泛型代碼,而不喜歡去設計開發自己的泛型代碼。
實現一個泛型類并沒有那么容易。對于類型參數,使用這段代碼的程序員可能想要內置( plugin) 所有的類。他們希望在沒有過多的限制以及混亂的錯誤消息的狀態下, 做所有的事情。因此, 一個泛型程序員的任務就是預測出所用類的未來可能有的所有用途。【這個難度是有點大的】
泛型程序設計劃分為 3 個能力級別。 基本級別是, 僅僅使用泛型類—典型的是像ArrayList 這樣的集合—不必考慮它們的工作方式與原因。大多數應用程序員將會停留在這一級別上,直到出現了什么問題。當把不同的泛型類混合在一起時,或是在與對類型參數一無所知的遺留的代碼進行銜接時, 可能會看到含混不清的錯誤消息。如果這樣的話,就需要學習 Java 泛型來系統地解決這些問題, 而不要胡亂地猜測。當然,最終可能想要實現自己的泛型類與泛型方法。
8.2 定義簡單泛型類
一個泛型類( generic class) 就是具有一個或多個類型變量的類。以一個 Pair 類為例:
// 類型變量 T 用“<>”,寫在類名后面 public class Pair<T> {private T first;private T second;public Pair() { first = null ; second = null ; }public PairfT first, T second) { this.first = first; this.second = second; }public T getFirstO { return first; }public T getSecondO { return second; }public void setFirst(T newValue) { first = newValue; }public void setSecond(T newValue) { second = newValue; } }泛型類可以有多個類型變量。例如, 可以定義 Pair 類,其中 第一個域 和 第二個域 使用不同的類型:
public class Pair<T, U> { . . . } // 用具體的類型替換類型變量就可以實例化泛型類型, 例如: Pair<String> // 可以將結果想象成帶有構造器的普通類: Pair<String> Pair<String>(String, String) // 和方法: String getFirstO String getSecond() void setFirst(String) void setSecond(String)換句話說,泛型類可看作普通類的工廠。
8.3 泛型方法
實際上,還可以直接定義一個帶有類型參數的簡單方法。
class ArrayAlg {// 定義在普通類中的泛型方法// 注意:類型變量修飾符放在方法修飾符后面,返回類型前面。// 當然這里的返回類型就是指定的泛型類型,參數也是.public static <T> T getMiddle(T... a){return a[a.length / 2];} }調用泛型方法:
// 當調用一個泛型方法時,在方法名前的尖括號中放人具體的類型 String middle = ArrayAlg.<String>getMiddle("John", "Q.", "Public");// 其實編譯器可以根據實際傳入參數,確定泛型類型,所以可以簡寫 String middle = ArrayAlg.getMiddle("John", "Q.", "Public");8.4 類型變量的限定(extends)
有時,類或方法需要對類型變量加以約束。未加限定的類型變量 T 相當于 Object,加上限定之后其表示范圍就變小了。
// 這里限定了類型變量 T 只能是實現了 Comparable 接口的類 public static <T extends Comparable> T min(T[] a){...}讀者或許會感到奇怪—在此為什么使用關鍵字 extends 而不是 implements ? 畢竟,Comparable 是一個接口。下面的記法
<T extends BoundingType>
表示 T 應該是綁定類型的子類型 (subtype)。 T 和綁定類型可以是類, 也可以是接口。選擇關鍵字 extends 的原因是更接近子類的概念, 并且 Java 的設計者也不打算在語言中再添加一個新的關鍵字(如 sub)。
一個類型變量或通配符可以有多個限定,例如:
<T extends Comparable & Serializable, U extends Response>
限定類型用 “&” 分隔,而逗號“,”用來分隔多個類型變量。
在 Java 的繼承中, 可以根據需要擁有多個接口超類型, 但限定中至少有一個類。如果用一個類作為限定,它必須是限定列表中的第一個。
?
總結
以上是生活随笔為你收集整理的《Java 核心技术卷1 第10版》学习笔记 ------ 泛型【基础】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决 centos7 最小化安装之后不能
- 下一篇: SessionStorage 和 Loc