-------------------------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培訓、期待與您交流!--------------------------