java泛型 type_Java泛型Type體系

最近看開源代碼,看到里面很多Java泛型,並且通過反射去獲取泛型信息。如果說要看懂泛型代碼,那還是比較容易,但是如果要自己利用泛型寫成漂亮巧妙的框架,那必須對泛型有足夠的了解。所以這兩三天就不在不斷地看Java泛型相關的東西。如果說想要明白通過反射去獲取泛型信息,那么Type體系是必須要了解的。Java從1.5開始引入泛型,並且也引入了Type體系。首先給出Type的類型樹UML圖,以便有個整體的認識。

aHR0cDovL2hvdXpoaS5tZS9waG90by91cGxvYWRzL2JpZy8xYWVmM2RiYTIwYWMwZjU4Y2E2Y2NiZGUxNWVlNTdhYS5wbmc=

這些都在java的reflect包下面,圖中帶有s的接口返回的是數組,由於畫圖工具的原因,標記的只有一個類型,沒有帶[]。可以說是Java泛型反射的基礎。這個UML圖我只選取了這些類與接口與Type相關的部分。

Method,Field,Constructor,Class與Type

Method,Field,Constructor都是與Type關聯的,而Class是Type的子類。從實際泛型中看也是這樣的,因為方法,域,構造方法都可以是泛型。

如果從來沒有接觸過這些,那么一開始接觸這些泛型的反射會非常突兀。如果從一些疑問,或者說需求開始思考可能會能夠更好地了解這些東西的作用,比如說:我們已經知道能夠通過反射(從1.1就開始支持了)獲得一個Class里面的方法以及域,但是我們怎么獲得一個帶有模版參數的Class里面的模版參數呢?比如說下面這個類class Test {

public void testMethod(R params){

}

}

我們怎么根據Test.class獲得T呢?獲得T的具體類型?Class實現了接口GenericDeclaration。GenericDeclaration的getTypeParameters()方法就可以獲得模版參數。

同樣Method能夠包含模版參數的地方有四個,模版參數,返回值,函數參數,異常。Method的四個方法分別對應這四個地方(有一個是繼承自GenericDeclaration)。Field,Constructor也都是類似。

Method,Field,Constructor,Class都有獲得聲明的模版參數的方法,這樣我們就可以通過反射來獲取模版參數類型。

Type的子接口

Type有四個子接口:ParameterizedType,TypeVariable,WildcardType,GenericArrayType。下面分別介紹這四個類型的具體表示的意思。假設我們申明有下面這個類public class GenericTest {

private Map map = null;

}

下面我們開始舉例說明。

ParameterizedType

ParameterizedType是表示泛型類型,比如說Mappublic static void testParameterizedType() throws NoSuchFieldException, SecurityException{

Type mapGenericType = GenericTest.class.getDeclaredField("map").getGenericType(); //ParameterizedType

if(mapGenericType instanceof ParameterizedType){

Type basicType = ((ParameterizedType) mapGenericType).getRawType();

System.out.println("basicType equals Map.class is " + (basicType ==Map.class)); //返回True

System.out.println("基本類型為:"+basicType); //Map

// 獲取泛型類型的泛型參數, 分別為

Type[] types = ((ParameterizedType) mapGenericType).getActualTypeArguments();

for (int i = 0; i < types.length; i++) {

System.out.println("第"+(i+1)+"個泛型類型是:"+types[i]);

}

//返回為 T1, class java.lang.Integer

System.out.println(((ParameterizedType) mapGenericType).getOwnerType()); //null

}

}

TypeVariable

這個是泛型參數類型,比如Mappublic static void testTypeVariable() throws NoSuchFieldException, SecurityException{

Type mapGenericType = GenericTest.class.getDeclaredField("map").getGenericType(); //ParameterizedType

if(mapGenericType instanceof ParameterizedType){

// 獲取泛型類型的泛型參數, 分別為 T1, class java.lang.Integer

Type[] types = ((ParameterizedType) mapGenericType).getActualTypeArguments();

for (int i = 0; i < types.length; i++) {

if( types[i] instanceof TypeVariable){

// T1 is TypeVariable, and Integer is not.

System.out.println("the "+(i+1)+"th is TypeVariable");

}else{

System.out.println("the "+(i+1)+"th is not TypeVariable");

}

}

}

System.out.println("GenericTest TypeVariable");

TypeVariable>[] typeVariables = GenericTest.class.getTypeParameters();

// console print T1, T2

for(TypeVariable tmp : typeVariables){

System.out.println(""+tmp);

Type[] bounds = tmp.getBounds(); //return upper bounds

if(bounds.length > 0){

//T2 has upper bounds which is class java.lang.Number,

//T1's upper bounds is Object which is default.

System.out.println("bounds[0] is: "+bounds[0]);

}

System.out.println("name is: "+tmp.getName()); // T1, T2

System.out.println("GenericDeclaration is equals GenericTest.class: "+ (tmp.getGenericDeclaration()==GenericTest.class)); //GenericTest

}

}

WildcardType

WildcardType是通配符類型,也就是? extends Number這種。可以獲得上下界。具體使用如下private Map extends Number, ? super Integer> map1 = new HashMap();

public static void testWildcardType() throws NoSuchFieldException, SecurityException{

Type mapGenericType = GenericTest.class.getDeclaredField("map1").getGenericType();

TypeVariable>[] typeVariables = GenericTest.class.getTypeParameters();

Type[] types = ((ParameterizedType) mapGenericType).getActualTypeArguments();

for(Type t : types){

if(t instanceof WildcardType){

System.out.println("wildcardType");

if( ((WildcardType) t).getLowerBounds().length > 0 )

System.out.println((((WildcardType) t).getLowerBounds())[0]); //print java.lang.Integer

if( ((WildcardType) t).getUpperBounds().length > 0 )

System.out.println((((WildcardType) t).getUpperBounds())[0]); //print java.lang.Number, Object

}

}

}

GenericArrayType

這個是數組泛型。比如T1[] tArray。這是變量的聲明。比如下面這段代碼private T1[] tArray = null;

public static void testGenericArrayType() throws NoSuchFieldException, SecurityException{

Type tArrayGenericType = GenericTest.class.getDeclaredField("tArray").getGenericType();

if(tArrayGenericType instanceof GenericArrayType){

System.out.println("is GenericArrayType"); //

Type t1 = ((GenericArrayType) tArrayGenericType).getGenericComponentType();

System.out.println(t1); // print T1

if( t1 instanceof TypeVariable){

System.out.println("t1 is TypeVariable");

System.out.println(((TypeVariable) t1).getGenericDeclaration());

}

}

}

Class

Class也是實現了Type接口。像前面的代碼中得到了java.lang.Integer等,就是返回Class。Class也可以通過getGenericInterfaces()獲取實現的接口,通過getGenericSuperclass()獲取父類的類型。

總結

整個Type體系主要就是前面介紹的內容了,從Method,Field,Class反射獲取Type,然后Type本身又有很多子類型,標明具體的泛型類型。這個是我測試的代碼源碼

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值