一、為什么要使用泛型程序設計
1、泛型程序設計:以為這編寫代碼可以被很多不同類型的對象所重用。例如:我們不必為了聚集String和File而別設計不同的類;
2、使代碼具有更好的可讀性:ArrayList<String> str = new ArrayList<>(); 人們一看就知道是包含了String對象的數組列表;
二、定義簡單的泛型類
泛型類:就是具有一個或多個類型變量的類。
聲明語法:public class ClassName<T> {...}
例:
public class Pair<T> { private T first; private T second; public Pair(){ first = null; second = null; } public Pair(T frist,T second){ this.first = first; this.second = second; } public T getFirst(){ return first; } public T getSecond(){ return second; } public void setFirst(T first){ this.first = first; } public void setSecond(T second){ this.second = second; } }
Pair 類引入了一個類型變量 T ,用 (<>)括起來,並放在類名后邊。泛型變量也可以有多個類型變量。例如:public class Pair<T,U>{.....}
注意:建議類型變量使用大寫字母,而且要比較短。泛型類要寫在一個單獨的文件中。
用具體的類型替換類型變量就可以實例化泛型類型:Pair<String> pair = new Pair(); 或 Pair pair = new Pair(String,String);
三、泛型方法:
例如:
class ArrayAlg{ public static <T> T getA (T a){ //方法體;
return a; } }
注意:泛型方法既可以在泛型類中定也可以在普通類中定義。類型變量放在修飾符的后邊,返回類型的前面。
方法的調用:String a = ArrayAlg.<String>gerA("hello world");在這種情況下(也是在大多數情況下)編譯器有足夠的信息能夠判斷所調用方法的類型,所以方法調用中可以省略<String>類型參數。
四、變量類型的限定
有時候我們要對類型變量加以約束,看下面的例子:
public class ArrayAlg { public static <T> T min(T[] a){ if(a == null || a.length == 0){ return null; } T smallest = a[0]; for(int i = 1;i < a.length;i++){ if(smallest.compareTo(a[i]) > 0) //error The method compareTo(T) is undefined for the type T return smallest = a[i]; } return smallest; } }
代碼中變量smallest 類型為T ,這意味着它可以是任意一個類的對象。那么問題來了,我們怎么才能確信T所屬的類有compareTo方法呢??解決這個問題的方法就是將T限制為實現了Comparable接口的類。可以通過對類型變量T設置限定實現這一點:
public static <T extends Comparable> T min(T[] a){........}
現在,泛型方法min只能被實現了Comparable接口的類(如String,LocalDate 等)的數組調用。
又一個問題出現了,眾所周知Comparable是一個接口那么為什么要用關鍵字extends 而不是 implements呢?
記法:<T extends BoundingType > 表示T應該是綁定類型的子類型,T和綁定類型都可以是類,也可以是接口。選擇關鍵字extends的原因是更接近於子類的概念。而且java設計者也不打算在語言中再添加一個新關鍵字了。
一個類型變量可以有多個限定,限定類型用“&” 分割,而逗號用來分割類型變量。例如:<T extends Comparable & Serializable,U extends String>
注意:可以根據需求有多個接口作為限定類,但是限定中至多有一個類。