泛型技術(shù)在C#和Java之中的使用方式看似相同伙窃,但實(shí)現(xiàn)上卻有著根本性的分歧,C#里面泛型無(wú)論在程序源碼中袁波、編譯后的IL中(Intermediate Language耻蛇,中間語(yǔ)言,這時(shí)候泛型是一個(gè)占位符)或是運(yùn)行期的CLR中都是切實(shí)存在的朝蜘,List<int>與List<String>就是兩個(gè)不同的類型恶迈,它們?cè)谙到y(tǒng)運(yùn)行期生成,有自己的虛方法表和類型數(shù)據(jù)谱醇,這種實(shí)現(xiàn)稱為類型膨脹暇仲,基于這種方法實(shí)現(xiàn)的泛型被稱為真實(shí)泛型。
Java語(yǔ)言中的泛型則不一樣副渴,它只在程序源碼中存在奈附,在編譯后的字節(jié)碼文件中,就已經(jīng)被替換為原來(lái)的原始類型(Raw Type煮剧,也稱為裸類型)了斥滤,并且在相應(yīng)的地方插入了強(qiáng)制轉(zhuǎn)型代碼,因此對(duì)于運(yùn)行期的Java語(yǔ)言來(lái)說(shuō)勉盅,ArrayList<int>與ArrayList<String>就是同一個(gè)類佑颇。所以說(shuō)泛型技術(shù)實(shí)際上是Java語(yǔ)言的一顆語(yǔ)法糖,Java語(yǔ)言中的泛型實(shí)現(xiàn)方法稱為類型擦除草娜,基于這種方法實(shí)現(xiàn)的泛型被稱為偽泛型挑胸。(類型擦除在后面在學(xué)習(xí))
使用泛型機(jī)制編寫(xiě)的程序代碼要比那些雜亂的使用Object變量,然后再進(jìn)行強(qiáng)制類型轉(zhuǎn)換的代碼具有更好的安全性和可讀性宰闰。泛型對(duì)于集合類來(lái)說(shuō)尤其有用茬贵。
在使用泛型之前,先了解下泛型的幾個(gè)基本概念移袍,以ArrayList<E>和ArrayList<Integer>做簡(jiǎn)要介紹:
整個(gè)成為ArrayList<E>泛型類型
ArrayList<E>中的 E稱為類型變量或者類型參數(shù)
整個(gè)ArrayList<Integer> 稱為參數(shù)化的類型
ArrayList<Integer>中的integer稱為類型參數(shù)的實(shí)例或者實(shí)際類型參數(shù)
·ArrayList<Integer>中的<Integer>念為typeof Integer
ArrayList稱為原始類型
泛型的使用
泛型有以下三種解藻,分別是泛型類、泛型接口和泛型方法
1.泛型類
1.1簡(jiǎn)單泛型類的使用
泛型類就是具有一個(gè)或多個(gè)類型變量的類咐容,泛型類是在多個(gè)方法簽名間實(shí)施類型約束舆逃。在 List<V> 中,類型參數(shù) V 出現(xiàn)在 get()戳粒、add()路狮、contains() 等方法的簽名中。當(dāng)創(chuàng)建一個(gè) Map<K, V> 類型的變量時(shí)蔚约,您就在方法之間宣稱一個(gè)類型約束奄妨。您傳遞給 add() 的值將與 get() 返回的值的類型相同。泛型類的使用很簡(jiǎn)單苹祟,如下
class Pair<T> {
private T value;
public Pair(T value) {
this.value=value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
使用的時(shí)候我們可以這樣定義Pair<String> pair=new Pair<String>("Hello");
Pair類引入了一個(gè)類型變量T砸抛,用尖括號(hào)<>括起來(lái)评雌,并放在類名的后面。泛型類可以有多個(gè)類型變量直焙。例如景东,可以定義Pair類,其中第一個(gè)域和第二個(gè)域使用不同的類型:public class Pair<T,U>{......}
1.2泛型返回類型的方法
下面的代碼列舉了使用一個(gè)在普通類ArrayAlg中返回類型為泛型的方法minmax奔誓,用其來(lái)獲取字符串?dāng)?shù)組words中的字符串字典排序斤吐。
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 = 1; 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<String>(min, max);
}
}
2.泛型接口
interface Show<T,U>{
void show(T t,U u);
}
class ShowTest implements Show<String,Date>{
@Override
public void show(String str,Date date) {
System.out.println(str);
System.out.println(date);
}
}
3.泛型方法
泛型方法是因?yàn)槟胍谠摲椒ǖ亩鄠€(gè)參數(shù)之間宣稱一個(gè)類型約束。如下:
3.1普通類中的泛型方法
public class Pair
{
public static <T> T getMiddle(T[] b) {
return b[b.length/2];
}
}
這個(gè)方法是用在普通類中定義的厨喂,而不是用在泛型類中定義和措。但是,這是一個(gè)泛型方法蜕煌,這一點(diǎn)可以從尖括號(hào)和類型變量中看出來(lái)派阱。 需要注意的是,類型變量放在修飾符的后面斜纪,返回類型的前面贫母。當(dāng)然泛型方法可以定義在普通類中,也可以定義在泛型類中傀广。
泛型方法的調(diào)用
String[] names = { "mmj", "geeeeg.", "sa" };
String middle = ArrayAlg.<String>getMiddle(names);
在這種情況下颁独,方法調(diào)用中可以省略掉<String>類型參數(shù)彩届。編譯器有足夠的信息來(lái)判斷出多調(diào)用的方法伪冰。它用的names的類型(即String[ ]類型)與泛型類型T[ ]進(jìn)行匹配,并且判斷出T一定是String樟蠕。也就是說(shuō)String middle = ArrayAlg.getMiddle(names)也是對(duì)的
3.2泛型類中的泛型方法
public class Pair<T>
{
public Pair() { first = null; second = null; }
public Pair(T middle){ this.middle = middle;}
//泛型方法
public T getSth1<T>(T t)
{
return t贮聂;
}
public void getSth2<T>(T t)
{
}
//非泛型方法
public T getMiddle(){return middle;}
private T middle;
public T length; //length要用public或者默認(rèn)訪問(wèn)修飾符
}
3.3泛型返回類型的泛型方法
class ArrayAlg
{
public static <T> Pair<T> getMiddle(T[] b) //這里的泛型方法返回類型為Pair<String>
{
return new Pair<T>(b[b.length / 2]); //b[b.length / 2]是T[]類型,所以無(wú)需強(qiáng)制類型轉(zhuǎn)換寨辩。
}
}
調(diào)用如下String[] names = { "mmj", "geeeeg.", "sa" };
Pair<String> middle = ArrayAlg.<String>getMiddle(names);
//如前所述Pair<String> middle = ArrayAlg.getMiddle(names);也可以吓懈。
參考:
1.http://blog.csdn.net/zzy7075/article/details/50467089##3