Java reflect Type类及其子类用法分析
来源:互联网 发布:网络女主播谈恋爱 编辑:程序博客网 时间:2024/06/05 06:20
在看源码之前我们先来了解一下什么是Type
首先:Type 是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型(Class)、参数化类型(Parameterized)、数组类型(GenericArrayType)、类型变量(TypeVariable)和基本类型(Class)。
首先我们先来看看其定义:
public interface Type { default String getTypeName() {//返回一个字符串描述该类型 return toString(); }}我们再来看看其继承体系
根据类图我们可以看到Type拥有4个已知的子类:
GenericArrayType 表示一种数组类型,其组件类型为参数化类型或类型变量。
ParameterizedType 表示参数化类型,如 Collection<String>
TypeVariable 是各种类型变量的公共高级接口。
WildcardType 表示一个通配符类型表达式,如 ?、? extends Number 或 ? super Integer。
以上为JDK API中的解释,看了似乎并没有搞明白其想说明什么
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
A.首先我们看一下ParameterizedType的接口定义
/** * ParameterizedType表示参数化类型,也就是泛型,例如List<T>、Set<T>等; */public interface ParameterizedType extends Type { //获取泛型中的实际类型,可能会存在多个泛型,例如Map<K,V>,所以会返回Type[]数组; Type[] getActualTypeArguments(); //获取声明泛型的类或者接口,也就是泛型中<>前面的那个值; Type getRawType(); //通过getOwnerType()方法可以获取到内部类的“拥有者”; //拥有者表示的含义--内部类的“父类”,例如: Map 就是 Map.Entry<K,V>的拥有者。 Type getOwnerType();}例子:
在下面的例子中ParamterizedType类拥有两个成员变量List<T> ,Set<String>我们获取到该类型之后会发现,他们都是ParamterizedTypeImpl类型,因为Set<String>和Set<Integer>实际上是一样的,都是泛型。
public class ParameterizedTypeTest<T> { private List<T> list=null; private Set<String> set=null; public static void main(String[] args) throws NoSuchFieldException{ Field fieldList=ParameterizedTypeTest.class.getDeclaredField("list"); //获取该属性的泛型类型 Type typeList=fieldList.getGenericType(); //获取实际的Type类型 System.out.println(typeList.getClass().getName()); //输出为: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl Field fieldSet=ParameterizedTypeTest.class.getDeclaredField("set"); //获取该属性的泛型类型 Type typeSet=fieldList.getGenericType(); //获取实际的Type类型 System.out.println(typeSet.getClass().getName()); //输出为: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl }}
我们再来看看其接口方法
首先是getActualTypeArguments : 根据名称,其实也可以猜出其作用:就是获取泛型参数的实际类型。有一点需要注意的是,Java的泛型采用的是擦除发实现了,那么在运行时又能动态的获取泛型的实际类型,就足以证明,泛型类型还是通过某种方式写入到了class文件中
例子如下:
public class ParameterizedTypeTest<T> { private List<T> list=null; private Set<Integer> set=null; private Map<String,Integer> map=null; private Map<Map<String,Integer>,Map<Object,Object>> map2=null; /** * 如果是ParameterizedTypeTest.class.getDeclaredField("map2"); * 那么结果如下: * System.out.println(types[0]); //输出为:java.util.Map<java.lang.String, java.lang.Integer> * System.out.println(types[1]); //输出为:java.util.Map<java.lang.Object, java.lang.Object> */ public static void testGetActualTypeArguments()throws NoSuchFieldException{ Field fieldMap=ParameterizedTypeTest.class.getDeclaredField("map"); Type typeMap=fieldMap.getGenericType(); ParameterizedType parameterizedTypeMap=(ParameterizedType)typeMap; Type[] types=parameterizedTypeMap.getActualTypeArguments(); System.out.println(types[0]); //输出为:class java.lang.String System.out.println(types[1]); //输出为:class java.lang.Integer } public static void main(String[] args) throws NoSuchFieldException{ testGetActualTypeArguments(); }}再来看看getRawType方法:获取声明泛型的类或者接口,说明了也就是这个泛型是被谁声明的,例子如下:
public class ParameterizedTypeTest<T> { private List<T> list=null; private Set<Integer> set=null; private Map<String,Integer> map=null; @Test public void testGetRawType() throws NoSuchFieldException{ Field fieldMap=ParameterizedTypeTest.class.getDeclaredField("map"); //getGenericType() 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型 Type typeMap=fieldMap.getGenericType(); ParameterizedType parameterizedTypeMap= (ParameterizedType) typeMap; Type type=parameterizedTypeMap.getRawType(); System.out.println(type.getTypeName()); //输出 java.util.Map }}
最后再来getOwnerType()方法
public class ParameterizedTypeTest<T> { private Map.Entry<String,Integer> mapEntry; @Test public void testGetRawType() throws NoSuchFieldException{ Field fieldMap=ParameterizedTypeTest.class.getDeclaredField("mapEntry"); //getGenericType() 返回一个 Type 对象,它表示此 Field 对象所表示字段的声明类型 Type typeMap=fieldMap.getGenericType(); ParameterizedType parameterizedTypeMap= (ParameterizedType) typeMap; Type type=parameterizedTypeMap.getRawType(); System.out.println(type.getTypeName()); //输出 java.util.Map$Entry System.out.println(parameterizedTypeMap.getOwnerType()); //输出 interface java.util.Map }}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
再来看看GenericArrayType
首先先看看定义
/** * 泛型数组类型,例如List<String>[] 、T[]等 */public interface GenericArrayType extends Type { /** * 返回泛型数组中元素的Type类型,即List<String>[] 中的 List<String>(ParameterizedTypeImpl)、 * T[] 中的T(TypeVariableImpl) */ Type getGenericComponentType();}例子:
public class GenericArrayTypeTest<T> { private T[] t; private List<String>[] listArray; @Test public void TestGetGenericComponentType()throws NoSuchFieldException{ Field fieldListArray=GenericArrayTypeTest.class.getDeclaredField("listArray"); Type typeListArray=fieldListArray.getGenericType(); System.out.println(typeListArray.getClass().getName()); //sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl Field fieldT =GenericArrayTypeTest.class.getDeclaredField("t"); Type typeT=fieldT.getGenericType(); System.out.println(typeT.getClass().getName()); //sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl } }
通过上述例子可以看出:GenericArrayType表示的是泛型数组类型
再来看看其接口方法:getGenericComponentType
public class GenericArrayTypeTest<T> { private T[] t; private List<String>[] listArray; public void TestGetGenericComponentType(String filedName)throws NoSuchFieldException{ Field fieldListArray=GenericArrayTypeTest.class.getDeclaredField(filedName); Type typeListArray=fieldListArray.getGenericType(); GenericArrayType genericArrayType=(GenericArrayType)typeListArray; Type type=genericArrayType.getGenericComponentType(); System.out.println(type.getTypeName()); } @Test public void print()throws NoSuchFieldException{ TestGetGenericComponentType("listArray"); //输出 java.util.List<java.lang.String> TestGetGenericComponentType("t"); //输出 T }}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
再来看看TypeVariable
/** * 泛型的类型变量,指的是List<T>、Map<K,V>中的T,K,V等值, * 实际的Java类型是TypeVariableImpl(TypeVariable的子类); * 此外,还可以对类型变量加上extend限定,这样会有类型变量对应的上限; */interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement { /** * 获得该类型变量的上限,也就是泛型中extend右边的值; * 例如 List<T extends Number> ,Number就是类型变量T的上限; * 如果我们只是简单的声明了List<T>(无显式定义extends),那么默认为Object; * 值得注意的是,类型变量的上限可以为多个,必须使用&符号相连接, * 例如 List<T extends Number & Serializable>;其中,& 后必须为接口; */ Type[] getBounds(); //获取声明该类型变量实体 D getGenericDeclaration(); //获取类型变量在源码中定义的名称; String getName(); //这个方法是JDK1.8中的新方法,目前还不清楚其作用 AnnotatedType[] getAnnotatedBounds();}先来看看用法:
public class TypeVariableTest<T> { private List<T> list; @Test public void testTypeVariable()throws NoSuchFieldException{ Field fieldList=TypeVariableTest.class.getDeclaredField("list"); Type typeList=fieldList.getGenericType(); ParameterizedType parameterizedTypeList=(ParameterizedType)typeList; Type[] types=parameterizedTypeList.getActualTypeArguments(); System.out.println(types[0].getClass().getName()); //输出 sun.reflect.generics.reflectiveObjects.TypeVariableImpl }}再来看看getBounds()方法
public class TypeVariableTest<T extends Number & Serializable & Comparable> { private T t; @Test public void testGetBounds()throws NoSuchFieldException{ Field fieldT=TypeVariableTest.class.getDeclaredField("t"); TypeVariable typeVariable= (TypeVariable) fieldT.getGenericType(); Type[] types=typeVariable.getBounds(); for(Type type : types){ System.out.print(type + " "); //输出 class java.lang.Number interface java.io.Serializable interface java.lang.Comparable } }}
默认的边界测试
public class TypeVariableTest<T> { private List<T> list; @Test public void testTypeVariable()throws NoSuchFieldException{ Field fieldList=TypeVariableTest.class.getDeclaredField("list"); Type typeList=fieldList.getGenericType(); ParameterizedType parameterizedTypeList=(ParameterizedType)typeList; Type[] types=parameterizedTypeList.getActualTypeArguments(); TypeVariable typeVariable=(TypeVariable)types[0]; Type[] types2=typeVariable.getBounds(); for(Type type : types2){ System.out.print(type + " "); //输出 class java.lang.Object } }}
再来看看getGenericDeclaration方法
public class TypeVariableTest<T> { private T t; @Test //获取声明该类型变量实体,也就是TypeVariableTest<T>中的TypeVariableTest; public void testGetGenericDeclaration()throws NoSuchFieldException{ Field fieldT=TypeVariableTest.class.getDeclaredField("t"); TypeVariable typeVariable=(TypeVariable)fieldT.getGenericType(); GenericDeclaration genericDeclaration=typeVariable.getGenericDeclaration(); System.out.println(genericDeclaration); //输出 class TypeVariableTest }}
里面涉及到了一个类 GenericDeclaration 顺便看看该类
含义为:声明类型变量的所有实体的公共接口;也就是说该接口定义了哪些地方可以定义类型变量(泛型);该类的继承结构如下:
也就是说,只有在以上三种子类中才可以定义泛型
public class TestGenericDeclarationForClass<T> { //测试在Class定义泛型}class TestGenericDeclarationForConstruct{ public <T> TestGenericDeclarationForConstruct(T t){ //测试在构造方法定义泛型 }}class TestGenericDeclarationForMethod{ public <T> void test(T t){ //测试在方法定义泛型 }}再来看看方法getName 这个方法就比较好理解了
public class TypeVariableTest<T> { private T t; @Test public void testGetName()throws NoSuchFieldException{ Field fieldT=TypeVariableTest.class.getDeclaredField("t"); TypeVariable typeVariable=(TypeVariable)fieldT.getGenericType(); System.out.println(typeVariable.getName()); //输出 T }}
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
再来看看Class类 (Class 类就不是接口,而是实现类了)
Type接口的实现类,是我们工作中常用到的一个对象;在Java中,每个.class文件在程序运行期间,都对应着一个Class对象,这个对象保存有这个类的全部信息;因此,Class对象也称之为Java反射的基础;
public class ClassTest { private ClassTest classTest; @Test public void testClass()throws NoSuchFieldException{ Field field=ClassTest.class.getDeclaredField("classTest"); Type type=field.getGenericType(); System.out.println(type); //class ClassTest }}
当我们没有声明泛型的时候,我们普通的对象就是一个Class类型,是Type中的一种;
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
最后再来看看 WildcardType
定义如下:
/** * 通配符表达式,表示通配符泛型 * 例如:List<? extends Number> 和 List<? super Integer>; */public interface WildcardType extends Type { //获取泛型变量的上边界(extends) Type[] getUpperBounds(); //获取泛型变量的下边界(super) Type[] getLowerBounds();}获取该对象例子:
public class WildcardTypeTest { private List<? extends Number> listNum; private List<? super String> listStr; public void testWildcardType(String fieldName)throws NoSuchFieldException{ Field fieldNum=WildcardTypeTest.class.getDeclaredField(fieldName); ParameterizedType parameterizedTypeNum= (ParameterizedType) fieldNum.getGenericType(); Type[] types=parameterizedTypeNum.getActualTypeArguments(); System.out.println(types[0].getClass()); } @Test public void print()throws NoSuchFieldException{ testWildcardType("listNum"); //输出 class sun.reflect.generics.reflectiveObjects.WildcardTypeImpl testWildcardType("listStr"); //输出 class sun.reflect.generics.reflectiveObjects.WildcardTypeImpl }}
在来看看方法getUpperBounds()
public class WildcardTypeTest { private List<? extends Number> listNum; private List<? super String> listStr; public void testWildcardType(String fieldName)throws NoSuchFieldException{ Field fieldNum=WildcardTypeTest.class.getDeclaredField(fieldName); ParameterizedType parameterizedTypeNum= (ParameterizedType) fieldNum.getGenericType(); Type[] types=parameterizedTypeNum.getActualTypeArguments(); WildcardType wildcardType=(WildcardType)types[0]; System.out.println(wildcardType.getUpperBounds()[0]); //System.out.println(wildcardType.getLowerBounds()[0]); } @Test public void print()throws NoSuchFieldException{ testWildcardType("listNum"); //输出 class java.lang.Number }}
最后再来看看方法getLowerBounds()
public class WildcardTypeTest { private List<? extends Number> listNum; private List<? super String> listStr; public void testWildcardType(String fieldName)throws NoSuchFieldException{ Field fieldNum=WildcardTypeTest.class.getDeclaredField(fieldName); ParameterizedType parameterizedTypeNum= (ParameterizedType) fieldNum.getGenericType(); Type[] types=parameterizedTypeNum.getActualTypeArguments(); WildcardType wildcardType=(WildcardType)types[0]; //System.out.println(wildcardType.getUpperBounds()[0]); System.out.println(wildcardType.getLowerBounds()[0]); } @Test public void print()throws NoSuchFieldException{ testWildcardType("listStr"); //输出 class java.lang.String }}
- Java reflect Type类及其子类用法分析
- properties类及其子类用法
- java.lang.reflect.Type
- 《Java源码分析》:ReferenceQueue、Reference及其子类
- 《Java源码分析》:ReferenceQueue、Reference及其子类
- 《Java源码分析》:ReferenceQueue、Reference及其子类
- Java Throwable类及其子类
- PacketFilter 包过滤类及其子类用法
- PacketFilter 包过滤类及其子类用法
- 基本的数据类型分析----java.lang.Number类及其子类分析
- JAVA reflect (反射) 分析类结构
- java reflect包分析
- java I/O FilterInputStream及其子类源码分析
- CharSequence及其子类用法总结
- list及其子类的用法
- Resource及其子类的分析
- Finder 及其子类的分析
- Finder 及其子类的分析
- 数据结构与算法·实验七
- pandas Dataframe行 列读取的方法
- 零散笔记
- python:NumPy基础(1),ndarray多维数组对象
- c#图片反色,取底色,照片底色效果
- Java reflect Type类及其子类用法分析
- Json解析开源框架--Gson 的基本使用
- 【Spring】bean对象创建的细节(五)
- some tips about python Two
- linux make和gdb
- 数据结构与算法·实验八
- 【图像融合】高斯金字塔
- 大话设计模式之总结2
- 【Spring】IOC容器--创建对象(六)