黑馬程序員-java基礎加強-JDK1.5新特性-泛型

-------------------------ASP.Net+Unity開發、.Net培訓、期待與您交流!--------------------------

JDK1.5新特性:泛型

泛型定義
泛型用<>來表示,來限定某一個容器裝入的元素類型。<>裏面填入的是元素的類型
------------------------------------------------------------------------
集合運用泛型之後的叫法
ArrayList<E> :泛型類型,E稱爲類型變量或者類型參數,E只能是引用數據類型,不能是
基本數類型。
ArrayList<Integer> :參數化的類型,Integer稱爲類型參數的實例
ArrayList:原始類型
<>:typeof  ArrayList<Integer> 讀作,ArrayList typeof Integer
------------------------------------------------------------------------
泛型的<>內的類型限定的幾種情況
a、<>裏面直接填入元素的類型,
如,ArrayList<Integer> al=new ArrayList<Integer>();
注意:
第一:參數化類型可以引用一個原始類型的對象,
Collection<String> collection =new ArrayList();
第二:原始類型可以引用一個參數化類型
Collection collection =new ArrayList<String>();
第三:參數化類型不考慮類型參數的繼承關係:
Vector<String> v=new Vector<Object>();
Vector<Object> v=new Vector<String>();//都是不對的。
第四:創建數組實例時,數組的元素不能使用參數化的類型
Vector<String> vector[]=new Vector<String>[10];//這是錯的。
b、<>裏面寫入?,即寫入通配符。它的特點
第一:? 通配符爲一個具體的類型,但是可以指向任意的類型。
如:Collection<?> collection=new ArrayList<Integer>();
第二:當一個容器使用的是通配符時,則此容器就不能使用與類型有關的方法
如,add(E e)方法。因爲對於此容器,並不知道它具體的指向什麼參數化類型的容器
所以並不能使用與類型有關的方法。
ArrayList<?> al2=new ArrayList<Integer>();
   al2.add(1);//不對。
第三:只能是Vector<?> v=new Vector<String>();而不能是Vector<String> v=new Vector<?>();
即通配符只能在左邊不能在右邊,即?通配符定義的變量主要用來用作引用。
總結:使用?通配符可以引用其他各種參數化的類型,?通配符定義的變量主要用來用作
引用,可以調用與參數無關的方法,不能調用與參數有關的方法。

練習:定義一個方法,用於打印任意參數化類型的集合中的所有數據。

                package cn.itcast.day2;
		import java.lang.reflect.Method;
		import java.util.ArrayList;
		import java.util.Collection;
		public class FanXingTest {
			public static void main(String[] args)throws Exception {
				// TODO Auto-generated method stub
				ArrayList<Integer> al=new ArrayList<Integer>();
				al.add(1);
				al.add(2);
				al.add(3);
				printElem(al);
			}
			//通過通配符來達到“打印任意參數化類型集合元素”的要求。
			public static void printElem(Collection<?> collection)throws Exception{
				System.out.println("未添加元素之前的size:"+collection.size());
				//不能直接調用collection.add("abc");可以利用反射來跳過編譯器來添加元素
				Method method = collection.getClass().getMethod("add", Object.class);
				method.invoke(collection, "abc");
				//可以調用與參數無關的方法
				System.out.println("添加元素之後的size:"+collection.size());
				//打印此集合中的元素
				for (Object object : collection) {
					System.out.println(object);	
				}	
			}
		}
c、向上限定
格式:<? extends Number>表示只能爲Number的子類或者Number
Vector<? extends Number> v=new Vector<Integer>();//對的
Vector<? extends Number> v=new Vector<String>();//錯的
Number的子類爲7中基本類型的引用類型表示形式,即爲Byte,Short,Integer,Boolean
,Float,Double,Character。
d、向下限定
格式:<? super Integer>表示只能爲Integer或者Integer的子類
Vector<? super Integer> v=new Vector<Number>();//對的
Vector<? super Integer> v=new Vector<Byte();//錯的,因爲Integer和Byte是平級的。
-------------------------------------------------------------------------

泛型原理
泛型只是給編譯器看的,即當編譯之後,class文件中不再有相關的泛型信息。
所以對於給定的參數化類型的集合,要想對它裏面添加別的類型的元素,只需
要跳過編譯器即可。
例子:

                package cn.itcast.day2;
		import java.lang.reflect.Method;
		import java.util.ArrayList;
		import java.util.Collection;
		public class FanXingTest2 {
			public static void main(String[] args) throws Exception{
				// TODO Auto-generated method stub
				Collection<Integer> collection=new ArrayList<Integer>();
				//通過反射獲得方法add
				Method method=collection.getClass().getMethod("add",Object.class);
				//利用反射得到的方法來想集合中添加元素
				method.invoke(collection,"abc");
				method.invoke(collection,1);
				System.out.println(collection.size());
				for (Object integer : collection) {
					System.out.println(integer);	
				}
			}
		}
------------------------------------------------------------------------
自定義泛型方法
1、即在方法的返回值類型前面上加上<>來自定義泛型方法
例子:
public static <T> void swap(T[] arr,int x,int y)
{
T temp=arr[x];
arr[x]=arr[y];
arr[y]=temp;
}
2、泛型可以定義在類上、方法上、構造方法上、靜態方法上、和異常上。
定義在異常上:
private static <T extends Exception> void sayHello()throws T
{
try
{
}
catch (Exception e)//注意此處捕捉異常必須是具體的異常,不能寫成
//T e
{
throw(T)e;
}
}
3、泛型也可以寫成<V extends 接口1&接口2>即表示V是實現了接口1和接口2的類或者它的子類。
4、在泛型中可以同時有多個類型參數,在定義他們時在尖括號中用逗號隔開
public static <K,V> V getValue(K key)
{
return map.get(key);
}
5、類型參數的類型推斷
a、若:static <E> void swap(E[] a,int x,int y),只有一處用到,則類型直接由調用此方法
時傳遞的參數類型或者返回值來決定泛型參數的類型。
b、static <T> T add(T a,T b),即多處用到了類型變量,則若幾處都對應同一種類型,則就確定爲
此類型。
c、若,static <T> void fill(T[] A,T v).多處用到且這幾處對應不同的類型,且無使用返回值,這時
取多個參數中的最大交集類型,eg fill(new Integer[3],3.5f),則對應Number。
d、若,static <T> T add(T a,T b);多處用到,且這幾處對應不同的類型,且有返回值類型,則優先考慮
返回值類型。int x=add(3,3.5f);若返回值不對再試別的。最後應該確定爲Number類型。
------------------------------------------------------------------------
自定義泛型類
1、作用:將泛型定義在類上,來達到類中的所有方法操作同一個類型。
例子:

               class FanXing<T>
		{
			public T get(int x)
			{
				return null;
			}
			public void delete(T x)
			{
			}
			public void update(T obj)
			{
			}
			//即對於靜態方法不能使用類上的泛型變量。
			public static <E> E getclass(E e)
			{
				return null;
			}
		}
------------------------------------------------------------------------
練習:

1、獲取HashMap集合中的元素

        package cn.itcast.day2;
	import java.util.HashMap;
	import java.util.Map;
	import java.util.Set;
	public class HashMapFan {
		public static void main(String[] args) {
			// TODO Auto-generated method stub
			HashMap<String,Integer> hm=new HashMap<String,Integer>();
			hm.put("a",1);
			hm.put("b",1);
			hm.put("c",1);
			hm.put("d",1);
			Set<Map.Entry<String,Integer>> set=hm.entrySet();
			for (Map.Entry<String,Integer> me : set) {
				System.out.println(me.getKey()+":::"+me.getValue());	
			}
		}
	}
2、通過反射獲得泛型的實際類型參數
分析:要想得到泛型的實際類型參數,即得到Vector<Integer> v=new Vector<Integer>()  
中的Integer則通過v是沒辦法得到此實際類型參數的,因爲當編譯器一編譯完,泛型就沒了。
那麼可以通過,public static void applyFan(Vector<Integer> v1){}這樣的方法來得到
此方法裏面的參數的類型,從而得到實際類型參數。
代碼:

                package cn.itcast.day2;
		import java.lang.reflect.Method;
		import java.lang.reflect.ParameterizedType;
		import java.lang.reflect.Type;
		import java.util.Vector;
		public class ReflectFan {
			public static void main(String[] args)throws Exception {
				// TODO Auto-generated method stub
				//通過反射得到此方法
				Method method =ReflectFan.class.getMethod("applyVector", Vector.class);
				//通過調用方法getGenericParameterTypes()來得到此方法的泛型參數類型。
				Type[] types=method.getGenericParameterTypes();
				//得到此參數的參數類型。
				ParameterizedType pType=(ParameterizedType)types[0];
				System.out.println(pType.getRawType());//class java.util.Vector
				//下面結果爲class java.lang.Integer
				System.out.println(pType.getActualTypeArguments()[0]);	
			}
			public static void applyVector(Vector<Integer> v){
				
			}
		}

-------------------------ASP.Net+Unity開發、.Net培訓、期待與您交流!--------------------------


詳情請查看:http://edu.csdn.net

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章