Java泛型Type体系
2015-11-03 15:11
531 查看
最近看开源代码,看到里面很多Java泛型,并且通过反射去获取泛型信息。如果说要看懂泛型代码,那还是比较容易,但是如果要自己利用泛型写成漂亮巧妙的框架,那必须对泛型有足够的了解。所以这两三天就不在不断地看Java泛型相关的东西。如果说想要明白通过反射去获取泛型信息,那么Type体系是必须要了解的。Java从1.5开始引入泛型,并且也引入了Type体系。首先给出Type的类型树UML图,以便有个整体的认识。
这些都在java的reflect包下面,图中带有s的接口返回的是数组,由于画图工具的原因,标记的只有一个类型,没有带[]。可以说是Java泛型反射的基础。这个UML图我只选取了这些类与接口与Type相关的部分。
如果从来没有接触过这些,那么一开始接触这些泛型的反射会非常突兀。如果从一些疑问,或者说需求开始思考可能会能够更好地了解这些东西的作用,比如说:我们已经知道能够通过反射(从1.1就开始支持了)获得一个Class里面的方法以及域,但是我们怎么获得一个带有模版参数的Class里面的模版参数呢?比如说下面这个类
我们怎么根据Test.class获得T呢?获得T的具体类型?Class实现了接口GenericDeclaration。GenericDeclaration的getTypeParameters()方法就可以获得模版参数。
同样Method能够包含模版参数的地方有四个,模版参数,返回值,函数参数,异常。Method的四个方法分别对应这四个地方(有一个是继承自GenericDeclaration)。Field,Constructor也都是类似。
Method,Field,Constructor,Class都有获得声明的模版参数的方法,这样我们就可以通过反射来获取模版参数类型。
下面我们开始举例说明。
这些都在java的reflect包下面,图中带有s的接口返回的是数组,由于画图工具的原因,标记的只有一个类型,没有带[]。可以说是Java泛型反射的基础。这个UML图我只选取了这些类与接口与Type相关的部分。
Method,Field,Constructor,Class与Type
Method,Field,Constructor都是与Type关联的,而Class是Type的子类。从实际泛型中看也是这样的,因为方法,域,构造方法都可以是泛型。如果从来没有接触过这些,那么一开始接触这些泛型的反射会非常突兀。如果从一些疑问,或者说需求开始思考可能会能够更好地了解这些东西的作用,比如说:我们已经知道能够通过反射(从1.1就开始支持了)获得一个Class里面的方法以及域,但是我们怎么获得一个带有模版参数的Class里面的模版参数呢?比如说下面这个类
class Test<T> { public <R> 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<T1,T2 extends Number> { private Map<T1 , Integer> 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<Class<GenericTest>>[] 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<Integer,Integer>(); public static void testWildcardType() throws NoSuchFieldException, SecurityException{ Type mapGenericType = GenericTest.class.getDeclaredField("map1").getGenericType(); TypeVariable<Class<GenericTest>>[] 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本身又有很多子类型,标明具体的泛型类型。这个是我测试的代码源码相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树
- [原创]java局域网聊天系统