在學習使用泛型定義一個簡單的類之前,首先需要嘮嗑幾句關於泛型的幾個概述:
1:從Java程序設計語言1.0版發佈以來,變化最大的部分就是泛型。
2:使用泛型機制編寫的程序代碼要比那些雜亂的使用Object變量,然後在進行強制類型轉換的的代碼具有更好的安全性和可讀性。
3:泛型程序設計意味着編寫的代碼可以被很多不同類型的對象所重用。
4:在Java中增加泛型類之前,泛型程序設計是用繼承實現的,使用這種方法有兩個問題:當獲取一個值時必須進行強制類型轉換;此外這裏也沒有錯誤檢查,也就是說可以向數組列表中添加任何類的對象。
5:泛型通過提供一個類型參數,用來指示元素類型,從而解決了使用繼承實現泛型的弊端,使得程序具有更好的可讀性和安全性。
好了,以上就是關於泛型的最基本的概述,下面正式敘述一下如何定義和使用一個簡單的泛型類。
一個泛型類就是具有一個或多個類型變量的類
下面是一個例子:
package GenericProgramma;
public class PairTest1 {
public static void main(String[] args) {
String[] words= {"Mary","had","a","little","lamb"};
Pair<String> mm=ArrayAlg.minmax(words);
System.out.println("min="+mm.getFirst());
System.out.println("max="+mm.getSecond());
}
}
class Pair<T>{
private T first;
private T second;
public Pair() {
first=null;
second=null;
}
public Pair(T first,T second) {
this.first=first;
this.second=second;
}
public T getFirst() {
return first;
}
public T getSecond() {
return second;
}
public void setFirst(T newValue) {
first=newValue;
}
public void setSecond(T newValue) {
second=newValue;
}
}
class ArrayAlg{
public static Pair<String> minmax(String[] a){
if(a==null || a.length==0) {
return null;
}
String min=a[0];
String max=a[0];
for(int i=0;i<a.length;++i) {
if(min.compareTo(a[i])>0) {
min=a[i];
}
if(max.compareTo(a[i])<0) {
max=a[i];
}
}
return new Pair<>(min,max);
}
}
上面這個程序從一個字符數組中找出最小和最大的字符串,並且以Pair類型返回,其中Pair就是一個簡單的泛型類。
下面,我麼來分析一下泛型類應該如何寫:
Pair類引入了一個類型變量T,用尖括號(<>)括起來,並放在類名後面,泛型類可以有多個泛型變量。例如,可以將Pair類定義成以下形式:class Pair<T,U>{...}
類定義中的類型變量指定方法的返回類型以及域和局部變量的類型。如private T first;
用具體的類型替換類型變量就可以實例化泛型類型,例如:Pair<String>
有一點需要注意:類型變量使用大寫形式,且比較短,這是很常見的。在庫中,使用變量E表示集合的元素類型。K和V分別表示表的關鍵字與值的類型,T(需要時還可以用臨近的字母U和S)表示任意類型。
以上是關於泛型類的定義和使用,下面就介紹關於泛型方法的定義和使用:
也是首先觀察一個示例:
package Generic;
import java.util.Arrays;
public class PairTest2 {
public static void main(String[] args) {
Integer[] testInt=new Integer[] {1,2,3,4,5,6,7};
System.out.println(Arrays.toString(testInt));
testInt=ArrayAlg.swap(testInt, 2, 34);
//這是完整寫法
//testInt=ArrayAlg.<Integer>swap(testInt, 2, 3);
//一般情況下省略類型參數不會出現問題,但是如果傳入
//參數,,編譯器不足以推斷出類型時就會出現錯誤
System.out.println(Arrays.toString(testInt));
}
}
class ArrayAlg{
//用於交換傳入數組的兩個下標的值
public static <T> T[] swap(T[] t,int index1,int index2) throws IndexOutOfBoundsException{
try {
T temp=t[index1];
t[index1]=t[index2];
t[index2]=temp;
}catch(IndexOutOfBoundsException e) {
throw e;
}
return t;
}
}
首先我們發現,這個泛型方法並不是在泛型類中定義的,也就是說,泛型方法不一定非得定義在泛型類中。
下面介紹一下詳細規則:
類型變量(尖括號中的變量)放在修飾符的後面,返回類型的前面。
當調用一個泛型方法時,在方法名前的尖括號中放入具體的類型。(有時候也可以省略)
最後,是關於類型變量的限定:
同樣地,先上例子:
package Generic;
public class PairTest3 {
public static void main(String[] args) {
Integer[] testInt=new Integer[] {1,2,6,5,7,3,2,1};
System.out.println(ArrayAlg.findMax(testInt));
}
}
class ArrayAlg{
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <T extends Comparable> T findMax(T[] a) throws IndexOutOfBoundsException{
T temp=a[0];
for(T t:a) {
if(t.compareTo(temp)>0)temp=t;
}
return temp;
}
}
觀察上面程序,我們使用了extends關鍵字,意思就是,只有實現了Comparable接口的類纔可以使用這個泛型方法。