Java基礎知識之泛型以及自定義泛型

之前的文章講過了反射內省枚舉註解和自定義註解

本篇講一下泛型

一、什麼是泛型和泛型的作用

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
	}
}

以上就是對泛型的一些學習和總結,如有不正確的地方,可以在評論區進行指正,一起學習一起進步,謝謝

發佈了86 篇原創文章 · 獲贊 74 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章