1. 程式人生 > >資料結構和演算法-->泛型

資料結構和演算法-->泛型

函式物件:

package test;

import java.util.Collection;
import java.util.Comparator;

/**
 * CaseInsensitiveCompare 就是函式物件
 * 具體使用是在main方法中的System.out.println(findMax(arr,new CaseInsensitiveCompare()));
 * @author Administrator
 *
 */
public class GenericMemoryCell {
	
	public static <AnyType> AnyType findMax(AnyType[] arr, Comparator<? super AnyType> cmp){
		
		int maxIndex = 0;
		
		for(int i=1; i<arr.length; i++){
			if(cmp.compare(arr[i], arr[maxIndex]) > 0 ){
				maxIndex = i;
			}
		}
		
		return arr[maxIndex];
		
	}
	
	public static void main(String[] args) {
		
		String[] arr = {"ZEBRA","alligator","crocodile"};
		System.out.println(findMax(arr,new CaseInsensitiveCompare()));
	}
	
}

class CaseInsensitiveCompare implements Comparator<String>{

	@Override
	public int compare(String o1, String o2) {
		// TODO Auto-generated method stub
		return o1.compareToIgnoreCase(o2);
	}
	
}

T代表泛型
?是萬用字元,不能用於宣告階段

 

使用泛型的一個比較大的作用是方便簡單並且避免了陣列的型別相容性導致的問題而且將執行時異常提前到了編譯時異常。
比如,在泛型之前如果要達到泛型的目的,可以使用Object和介面兩種形式:
 

使用Object的一個問題是需要強制型別轉換。寫入的時候先轉換成了object然後讀出的時候仍然是object因此要做強制型別轉換。
使用介面形式:

這種方式必須要求傳遞的物件實現相應的介面,

陣列型別的相容性:
設Employee IS-A Person,那麼是不是也意味著Employee[] IS-A Person[],換句話說如果一個程式接收Person[]作為引數,那麼能不能將Emplyee[]
作為引數傳遞?實際上是可以的,但是還有一種比較複雜的情況,假設除了Employee外還有Student IS-A Person,此時考慮下面兩條複製語句:
Person[] arr = new Eemployee[5];
arr[0] = new Student(...);
兩句都能編譯,而實際上arr[0]引用了一個Employee,可是Student IS-NOT-A Employee,這樣就產生了混亂。執行時也不報錯因為不存在型別轉換。
比如上例中的介面形式的程式碼。

使用泛型時

在第五行,例如類GenericMemoryCell<String>的write方法需要一個String,傳入其他型別將產生一個編譯錯誤。
也可以宣告介面是泛型的比如Comparable,在java5之前不是泛型的他的compareTo方法接收一個Objet作為引數,因此傳遞給他的引數即使不是個
合理的型別也會編譯,只是在執行的時候報ClassCaseException。但是使用泛型的話在編譯器就能提示處錯誤。

泛型集合不具有型別相容性

可以使用萬用字元來實現如上要求

萬用字元可以不帶任何限制使用比如<?>相當於<? extends Object> 或者用super來標識超類而非子類

 

泛型方法:

有下列原因使用泛型方法: