泛型指引數化型別的能力,可以定義帶泛型型別的類或方法,隨後編譯器會用具體的型別來替換它。
在泛型產生之前,像集合的訪問都是靠強制型別轉換:
public class arraylist
public void add(object o)
...}
string filename = (string) names.get(0);
這樣沒有進行錯誤檢查,在執行時可能發生型別轉換錯誤,程式設計時必須小心。
泛型提供了型別引數,放在一對尖括號中。像這樣被稱為 形式泛型型別(formal generic type),隨後可以用乙個實際具體型別(actual concrete type)來替換,這個過程叫泛型例項化(generic instantiation)。
arraylistnames = new arraylist();
型別引數string說明了list中只存放string物件,當呼叫get的時,不需要手動進行型別轉換,編譯器會幫我們完成這個過程,並返回string。當呼叫add時,編譯器會進行檢查,傳入非string型別的引數,編譯不能通過。
泛型的加入,使得能夠在編譯時而不是在執行時檢測出型別錯誤。提高**的可靠性和可讀性。
注意, 泛型必須是引用型別,不能是基本型別,int, double這種需要用integer,double等替換。
泛型類: 定義乙個類為泛型型別,需要將型別引數放在類名之後。
public class pair
public void setfirst(t first)
public t getsecond()
public void setsecond(t second)
}
型別引數命名規則:e-集合,k-key,v-value,t-任意型別。
泛型方法:泛型方法既可以定義在普通類中,也可以定義在泛型類中。
定義乙個方法為泛型型別,需要將型別引數放在方法返回型別之前:
public static t getmiddle(t a)
呼叫這個方法:
public class test ;
string middle = test.getmiddle(names);
} ...
型別引數也可以省略:
public class test ;
string middle = getmiddle(names);
} ...
型別變數的限定:
將泛型指定為另外一種泛型的子型別,這種泛型型別稱為受限泛型(bounded)
t和繫結型別可以是類,也可以是介面。
乙個型別變數或者萬用字元可以有多個限定:
t extends comparable & serializable
&分隔限定型別,逗號分隔型別變數:
public class interval
public void setfirst(object first)
public object getsecond()
public void setsecond(object second)
}
因為t沒有限定型別,所以用object替換。
另乙個例子:
public class interval else
}}
型別擦除後:
public class interval else
}}
如果調換comparable 和serializable的順序,原始型別會用serializable替換t,在方法體內會執行comparable 的強制型別轉換,所以為了提高效率,一般應該將沒有方法的介面放在最後。
方法的型別擦除:
public static t min(t a)
擦除後:
public static comparable min(comparable a)
如果乙個方法的返回型別是泛型變數,由於進行了型別擦除,在呼叫這個方法後,返回值會被進行型別強制轉換:
pairp = ...
employee e = p.getfirst();
擦除getfirst返回型別後將返回object型別,虛擬機會進行強制型別轉換,以上語句,會被翻譯為2條虛擬機器指令:
1.對原始方法getfrist的呼叫
2.將返回的oject型別強制轉換為employee型別
通配泛型型別:
? extends t : 受限通配
現有方法 print輸出employee 的姓名:
public class employee
public void setname(string name)
@override
public string tostring()
}
public class manager extends employee
public class test
public static void print(pairp)
}
儘管manager 是employee的子類,但是不能這樣呼叫:
pairp2 = new pair();
print(p2); //編譯不過
這時需要使用萬用字元,
public static void print(pair<? extends employee> p)
輸出: tim and hank
注意: employee first = p.getfirst();可以正常呼叫,但是setfirst引數不能傳入 employee的例項,而只能傳入manager的例項。
因為型別引數是<? extends employee>編譯器只知道是 employee的子型別,父類引用子類是合法的,所以可以將getfirst的返回值賦給乙個employee物件,而employee子類不包含employee本身,所以在set方法中不能傳入employee的例項。
? super t : 下限通配:
? super manager 這個萬用字元限制為manager及其所有超型別。
這個萬用字元的行為和上面相反,它可以使用manager作為方法的引數,但是不能使用返回值:
pairp3 = new pair();
p3.setfirst(manager);
p3.setsecond(manager2);
print2(p3);
public static void print2(pair<? super manager> p)
注意這裡 p.getfirst()返回的是object物件,因為 ? super manager,編譯器只知道是 manager的超類,並不知道具體的類。這段**只是為了說明問題,實際上是不合適的。
實際應用舉例:根據提供的manager陣列引數,提供排序後的pair物件。
public static void minmax (manager a, pair<? super manager> result)
manager min = a[0];
manager max = a[0];
for (int i = 0; i < a.length; i++)
if (max.getname().compareto(a[i].getname()) < 0)
} result.setfirst(min);
result.setsecond(max);
}
簡單說就是,下限通配可以寫入,受限通配可以讀取。
?:無限定通配:
像pair<?> 這樣的?萬用字元叫做無限定通配,使用它不需要知道實際的型別:
public boolean hasnulls(pair<?> p)
無限定萬用字元也可以用具體型別變數替代:
public boolean hasnulls2(pairp)
但是前者的可讀性更強。 Java泛型總結
1 泛型主要是用來年解決資料型別安全的問題,用標識來代替屬性的型別或者返回值的型別 2 在使用泛型的時候可以有以下幾種形式 泛型介面 泛型類 萬用字元做泛型引數 泛型方法 泛型陣列 3 以下通過 說明 package com.sun.demo 一 定義泛型介面 inte ce father 二 定義...
java泛型總結
1.概念 泛型實現了引數化型別的概念,其最初的目的是希望類或方法能夠具備最廣泛的表達能力。通俗來說就是為了避免轉換出錯,限制資料型別。通過解耦類或者方法與所使用的型別之間的約束。list thelist1 new arraylist arrays.aslist 1,2,3,string for ob...
java泛型總結
提高 的復用性 1.泛型類 package xinceshi class box public t get public class iotest 2.泛型函式class util 呼叫的時候和呼叫普通函式一樣,不用加尖括號 3.邊界符public static int greaterthan t ...