JAVA反射_TYPE类型
来源:互联网 发布:淘宝日系男装店铺 编辑:程序博客网 时间:2024/06/07 14:13
java.lang.reflect
接口 Type
所有已知子接口:
GenericArrayType, ParameterizedType, TypeVariable<D>, WildcardType
所有已知实现类:
Class
public interface Type
Type 是 Java 编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型变量和基本类型。
从以下版本开始:
1.5
重点是上面的“所有类型”,它并不是我们平常工作中经常使用的 int、String、List、Map等数据类型,而是从Java语言角度来说,对基本类型、引用类型向上的抽象。
Type体系中类型的包括:原始类型(Class)、参数化类型(ParameterizedTypes)、数组类型(GenericArrayType)、类型变量(TypeVariable)、基本类型;
原始类型,不仅仅包含我们平常所指的类,还包括枚举、数组、注解等;
参数化类型,就是我们平常所用到的泛型List、Map;
数组类型,并不是我们工作中所使用的数组String[] 、byte[],而是带有泛型的数组,即T[] ;
基本类型,也就是我们所说的java的基本类型,即int,float,double等。
1.ParameterizedType
ParameterizedType 表示参数化类型,也就是泛型,如 Collection<String>。
需要注意的是,并不只是 Collection<String> 才是 parameterized,任何类似于 ClassName 这样的类型都是 ParameterizedType,
比如下面的这些都是 parameterizedType:
Map<String, Person> map;Set<String> set1;Class<?> clz;Holder<String> holder;List<String> list;//自定义的泛型类public class Demo<T> {}//自定义接口public interface Call<T> {}
获取ParameterizedType的例子:
public class ParameterizedTest<T> { private List<T> list = null; public static void main(String[] args) { try { Field field = ParameterizedTest.class.getDeclaredField("list"); Type type = field.getGenericType();//method的返回类型如果是泛型,可以用method.getGenericReturnType()获取 if (type instanceof ParameterizedType) { System.out.println(type); } } catch (NoSuchFieldException e) { e.printStackTrace(); } }}
ParameterizedType 的几个主要方法:
Type[] getActualTypeArguments(); //返回表示此类型实际类型参数的 Type 对象的数组。Type getRawType();//返回 Type 对象,表示声明此类型的类或接口。Type getOwnerType();//返回 Type 对象,表示此类型是其成员之一的类型。
1.1 getActualTypeArguments
获取泛型中的实际类型,可能会存在多个泛型,例如Map<K,V>,所以会返回Type[]数组:
public class ParameterizedTest<T> { private Map<String, Integer> list = null; public static void main(String[] args) { try { Field field = ParameterizedTest.class.getDeclaredField("list"); Type type = field.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; Type[] types = pType.getActualTypeArguments(); System.out.println(types[0]);// class java.lang.String System.out.println(types[1]);// class java.lang.Integer } } catch (NoSuchFieldException e) { e.printStackTrace(); } }}值得注意的是,无论<>中有几层嵌套(List<Map<String,Integer>),getActualTypeArguments()方法永远都是脱去最外层的<>(也就是List<>),
将<>号内的内容(Map<String,Integer>)返回;
我们经常遇到的List<T>,通过getActualTypeArguments()方法,得到的返回值是TypeVariableImpl对象,也就是TypeVariable类型(后面介绍)。
1.2 getRawType
获取声明泛型的类或者接口,也就是泛型中<>前面的那个值:
public class ParameterizedTest<T> { private Map<String, Integer> list = null; public static void main(String[] args) { try { Field field = ParameterizedTest.class.getDeclaredField("list"); Type type = field.getGenericType(); if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; Type t = pType.getRawType();//interface java.util.Map System.out.println(t); } } catch (NoSuchFieldException e) { e.printStackTrace(); } }}
1.3 getOwnerType
(这个比较少用到) 返回的是这个 ParameterizedType 所在的类的 Type (注意当前的 ParameterizedType 必须属于所在类的 member)。
比如 Map<String,Person> map 这个 ParameterizedType 的 getOwnerType() 为 null,而 Map.Entry<String, String>entry 的 getOwnerType() 为 Map 所属于的 Type。
2.TypeVariable
类型变量,即泛型中的变量;例如:T、K、V等变量,可以表示任何类,实际的Java类型是TypeVariableImpl(TypeVariable的子类)。在这需要强调的是,
TypeVariable代表着泛型中的变量,而ParameterizedType则代表整个泛型。此外,还可以对类型变量加上extend限定,这样会有类型变量对应的上限。
public class ParameterizedTest<T> { private List<T> list = null; public static void main(String[] args) { try { Field field = ParameterizedTest.class.getDeclaredField("list"); Type type = field.getGenericType();//获取List<T> if (type instanceof ParameterizedType) { ParameterizedType pType = (ParameterizedType) type; Type[] t = pType.getActualTypeArguments();// 获取T System.out.println(t[0].getClass().getName());//T的类型 sun.reflect.generics.reflectiveObjects.TypeVariableImpl } } catch (NoSuchFieldException e) { e.printStackTrace(); } }}在TypeVariable接口中,有3个方法,分别为getBounds()、getGenericDeclaration()、getName():
2.1 getBounds
获得该类型变量的上限,也就是泛型中extend右边的值;例如 List<T extends Number> ,Number就是类型变量T的上限;
如果我们只是简单的声明了List<T>(无显式定义extends),那么默认为Object。
//无显式定义extends:public class ParameterizedTest<T> { private T list = null; public static void main(String[] args) { try { Field field = ParameterizedTest.class.getDeclaredField("list"); Type type = field.getGenericType(); if (type instanceof TypeVariable) { TypeVariable tv = (TypeVariable) type; Type[] types = tv.getBounds(); for (Type t : types) { System.out.println(t);//class java.lang.Object } } } catch (NoSuchFieldException e) { e.printStackTrace(); } }}
//显式定义extends:public class ParameterizedTest<T extends Number & Serializable & Comparable> { private T t; public static void main(String[] args) { try { Field field = ParameterizedTest.class.getDeclaredField("t"); Type type = field.getGenericType(); if (type instanceof TypeVariable) { TypeVariable tType = (TypeVariable) type; Type[] types = tType.getBounds(); for (Type t : types) { System.out.println(t);//class java.lang.Number interface java.io.Serializable interface java.lang.Comparable } } } catch (NoSuchFieldException e) { e.printStackTrace(); } }}
2.2 getGenericDeclaration
获取声明该类型变量实体(是Class, Constructor, Method)
public class ParameterizedTest<T> { private T t; public static void main(String[] args) { try { Field field = ParameterizedTest.class.getDeclaredField("t"); Type type = field.getGenericType(); if (type instanceof TypeVariable) { TypeVariable tType = (TypeVariable) type; GenericDeclaration genericDeclaration = tType.getGenericDeclaration(); System.out.println(genericDeclaration);//class com.king.testreflect.ParameterizedTest } } catch (NoSuchFieldException e) { e.printStackTrace(); } }}
2.3 getName
获取类型变量在源码中定义的名称。
public class ParameterizedTest<T> { private T t; public static void main(String[] args) { try { Field field = ParameterizedTest.class.getDeclaredField("t"); Type type = field.getGenericType(); if (type instanceof TypeVariable) { TypeVariable tType = (TypeVariable) type; String name = tType.getName(); System.out.println(name);//T } } catch (NoSuchFieldException e) { e.printStackTrace(); } }}
说到TypeVariable类,就不得不提及Java-Type体系中另一个比较重要的接口---GenericDeclaration;
含义为:声明类型变量的所有实体的公共接口;也就是说该接口定义了哪些地方可以定义类型变量(泛型);
通过查看源码发现,GenericDeclaration下有三个子类,分别为Class、Method、Constructor;也就是说,我们定义泛型只能在一个类中这3个地方自定义泛型;
java.lang.reflect
接口 GenericDeclaration
所有已知实现类:
Class, Constructor, Method
此时,我们不禁要问,我们不是经常在类中的属性声明泛型吗,怎么Field没有实现 GenericDeclaration接口呢?
其实,我们在Field中并没有声明泛型,而是在使用泛型而已!不信,我们实际上代码来看看!
1.在Class上定义泛型:
public class GenericDeclarationTest<T> {//Class定义泛型}2.直接在构造方法上定义泛型
public class GenericDeclarationTest<T> {public <T> GenericDeclarationTest(T t) {//泛型构造函数}}
3.直接在普通方法上定义泛型
public class GenericDeclarationTest<T> {public <T> test(T t) {//泛型方法}}
4.直接在属性上定义(不支持)
public class GenericDeclarationTest {private T t;private List<T> list;}
我们看到,如果不在Class上定义,属性上并不能直接使用!
所以,这也是我之前说的属性上并不是定义泛型,而是使用泛型,所以Field并没有实现GenericDeclaration接口!
3.GenericArrayType
泛型数组类型.
简单来说就是:范型数组,组成数组的元素中有范型,则实现了该接口; 它的组成元素是ParameterizedType或TypeVariable 类型
public class ParameterizedTest<T> { private T[] t; private List<String>[] listArray; public static void main(String[] args) { try { Field fieldT = ParameterizedTest.class.getDeclaredField("t"); Type typeT = fieldT.getGenericType(); //sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl System.out.println(typeT.getClass().getName()); Field fieldListArray = ParameterizedTest.class.getDeclaredField("listArray"); Type typeListArray = fieldListArray.getGenericType(); //sun.reflect.generics.reflectiveObjects.GenericArrayTypeImpl System.out.println(typeListArray.getClass().getName()); } catch (NoSuchFieldException e) { e.printStackTrace(); } }}在GenericArrayType接口中,仅有1个方法,就是getGenericComponentType();
3.1 getGenericComponentType
返回泛型数组中元素的Type类型,即List<String>[] 中的 List<String>(ParameterizedTypeImpl)、T[] 中的T(TypeVariableImpl);
值得注意的是,无论是几维数组,getGenericComponentType()方法都只会脱去最右边的[],返回剩下的值。
4.WildcardType
?---通配符表达式,表示通配符泛型,例如:List<? extends Number> 和 List<? super Integer>。
但是WildcardType并不属于Java-Type中的一种。
extends 用来指定上边界,没有指定的话上边界默认是 Object, super 用来指定下边界,没有指定的话为 null。
public class ParameterizedTest<T> { private List<? extends Number> listNum; private List<? super String> listStr; public static void main(String[] args) { try { Field fieldNum = ParameterizedTest.class.getDeclaredField("listNum"); Type typeNum = fieldNum.getGenericType(); if (typeNum instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) typeNum; Type[] types = parameterizedType.getActualTypeArguments(); if (types[0] instanceof WildcardType) { WildcardType wType = (WildcardType) types[0]; Type[] upperTypes = wType.getUpperBounds(); for (Type t : upperTypes) { System.out.println(t);//class java.lang.Number } Type[] lowerTypes = wType.getLowerBounds();//null for (Type t : lowerTypes) { System.out.println(t); } } } Field fieldList = ParameterizedTest.class.getDeclaredField("listStr"); Type typeList = fieldList.getGenericType(); if (typeList instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) typeList; Type[] types = parameterizedType.getActualTypeArguments(); if (types[0] instanceof WildcardType) { WildcardType wType = (WildcardType) types[0]; Type[] upperTypes = wType.getUpperBounds(); for (Type t : upperTypes) { System.out.println(t);// class java.lang.Object } Type[] lowerTypes = wType.getLowerBounds(); for (Type t : lowerTypes) { System.out.println(t);//class java.lang.String } } } } catch (NoSuchFieldException e) { e.printStackTrace(); } }}
- JAVA反射_TYPE类型
- java反射---获取类型信息
- Java反射机制之类类型
- java反射(得到属性名,类型)
- 深入java--类型信息(反射)
- java技巧:反射判断field类型方法
- Java反射通过class获取父类泛型类型
- Java反射获取泛型类型
- Java反射字段类型的判断
- java运行时类型鉴定和反射
- bat知识点9_type
- 利用java反射实现Java Bean 类型转换
- ES _type 的相关整理
- Java反射获取基本类型、包装类型、String对象类型的字段值
- Java RTTI 运行时类型识别 和反射
- JDK1.4 不支持对java基本类型的反射
- java 通过反射获取泛型的类型
- 《Java编程思想》之类型检查(RTTI与反射机制)
- FPN(Linux下的实验和Windows平台的移植)
- JVM(十)垃圾回收器
- 信息摘要算法的简单实现
- 跨域-解决服务端session使用问题
- 中间件kingshard入门(二):orzdba监控工具
- JAVA反射_TYPE类型
- 自顶向下,逐步求精
- 跨域问题解决
- 解决recyclerview 在 scrollview 中不能全部显示,高度不正常的问题
- shell脚本调试
- Java和C#下String类型中的==和equals的原理与区别
- Android笔试和面试常见题目(四)
- android Zxing在fragment中使用
- AMQP 协议详解