本篇講一下泛型
一、什麼是泛型和泛型的作用
JDK5以前,對象保存到集合中就會失去其特性,取出時通常要程序員手工進行類型的強制轉換
這樣不可避免就會引發程序的一些安全性問題。例如:
ArrayList list = new ArrayList();
list.add("abc");
Integer num = (Integer) list.get(0); //運行時纔會報錯,在編譯時發現不了
再例如:在遍歷集合的時候,無法遍歷,因爲放入集合中的數據類型是不確定的
List list = new ArrayList();
//放入集合一個int型的
list.add(1);
//放入集合一個String類型的
list.add("fuck");
所以JDK5以後出現了泛型,泛型允許程序員在編寫集合代碼時就限制集合的處理類型,從而把原來程序運行時可能發生問題,轉變爲編譯時的問題,以此提高程序的可讀性和穩定性。
***注意:泛型是提供給javac編譯器使用的,它用於限定集合的輸入類型,讓編譯器在源代碼級別上,即擋住向集合中插入非法數據。但編譯器編譯完帶有泛型的java程序後,生成的class文件中將不再帶有泛型信息,以此使程序運行效率不受到影響,這個過程稱之爲“擦除”。
二、泛型的典型應用
(1)使用增強for循環迭代泛型集合中的元素。
@Test//泛型遍歷List集合
public void test2(){
List<String> list = new ArrayList<String>();
list.add("u");
list.add("fuck");
for(String s:list){
System.out.println(s);
}
}
(2)存取HashMap中的元素。
@Test//泛型遍歷Map,方式一
public void test3(){
Map<Integer, String> map = new LinkedHashMap<Integer, String>();
map.put(1, "aaa");
map.put(2, "bbb");
map.put(3, "ccc");
Set<Integer> keys = map.keySet();
for(Integer i:keys){
String value = map.get(i);
System.out.println("key:"+i+"\tvalue:"+value);
}
}
@Test//泛型遍歷Map,方式二
public void test4(){
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("a", "aaa");
map.put("b", "bbb");
map.put("c", "ccc");
Set<Map.Entry<String, String>> set = map.entrySet();//Set中的元素是Map.Entry類型的
for(Map.Entry<String, String> me:set){
String key = me.getKey();
String value = me.getValue();
System.out.println("key:"+key+"\tvalue:"+value);
}
}
使用泛型時的幾個常見問題:
a、使用泛型時,泛型類型須爲引用類型,不能是基本數據類型
b、如果等號左右兩邊都用到了泛型,則泛型裏的類型必須一模一樣。如以下的兩種就不行
ArrayList<String> list = new ArrayList<Object>();
ArrayList<Object> list = new ArrayList<String>();
c、只有一邊使用泛型,另一邊不使用泛型是允許的。如下邊的兩種形式是可以的
ArrayList<String> list = new ArrayList ();
ArrayList list = new ArrayList<String>();
這麼做的目的是爲了兼容
舉個例子
@Test
public void test5(){
//JDK1.5以後的新時代程序員調老程序員寫的東西
List<String> list = getList();
//一個老程序員調用新程序員寫的東西
List li = getAnthorList();
}
//一個老程序員寫的方法如下
public List getList(){
return null;
}
//一個新時代程序員寫的方法如下
public List<String> getAnthorList(){
return null;
}
三、自定義泛型的語法
Java程序中的普通方法、構造方法和靜態方法中都可以使用泛型。
方法使用泛型前,必須對泛型進行聲明,語法:<T> ,T可以是任意字母,但通常必須要大寫。一般情況下大寫是類型,小寫是參數。
<T>需放在方法的返回值聲明之前。
public class Demo2 {
public <T> void m1(T t){
}
public <T> T m2(T t){
return t;
}
public static <T> T m3(T t){
return t;
}
}
除了在方法上聲明泛型之外,還可以在類上聲明泛型,但是需要注意的是:在類上面聲明泛型,僅限於實例方法上直接使用,但是不適合靜態方法
例如:
//在類上面聲明泛型,在實例方法上直接用即可;但是不適合靜態方法
//靜態方法上使用的泛型聲明必須單獨定義
public class Demo2<T> {
public void m1(T t){
}
public T m2(T t){
return t;
}
}
上邊就是泛型的基本語法和使用
四、使用泛型練習幾個案例
(1)編寫一個泛型方法,實現數組元素的交換。
//自定義泛型練習
public class GenericUtil {
//顛倒任意數組中的指定位置上的兩個元素
//比如[1,2,3] 顛倒0和2位置上的元素 [3,2,1]
public static <T> void m1(T[] t,int index1,int index2){
//臨時變量
T temp = t[index1];
t[index1] = t[index2];
t[index2] = temp;
}
}
public class Demo3 {
@Test
public void test1(){
String s1[] = {"a","b","c"};
GenericUtil.m1(s1, 1, 2);
List list = Arrays.asList(s1);
System.out.println(list);
}
}
最後輸出結果爲 a,c,b
(2)編寫一個泛型方法,接收一個任意數組,並顛倒數組中的所有元素。
//自定義泛型練習
public class GenericUtil {
//顛倒任意類型數組中的元素順序
//[1,2,3] [3,2,1]
public static <T> void reverse(T[] t){
int startIndex = 0;
int endIndex = t.length -1;
while(startIndex<endIndex){
T temp = t[startIndex];
t[startIndex] = t[endIndex];
t[endIndex] = temp;
startIndex++;
endIndex--;
}
}
}
public class Demo3 {
@Test
public void test2(){
String s1[] = {"a","b","c"};
GenericUtil.reverse(s1);
List list = Arrays.asList(s1);
System.out.println(list);//輸出結果爲c,b,a
Integer ii[] = {1,2,3};
GenericUtil.reverse(ii);//注意:只有引用類型才能作爲泛型方法的實際參數
list = Arrays.asList(ii);
System.out.println(list);//輸出結果爲3,2,1
}
}
以上就是對泛型的一些學習和總結,如有不正確的地方,可以在評論區進行指正,一起學習一起進步,謝謝