java反射解决的是动态创建对象的问题,当然类是固定的;类如果是动态的,那就是字节码技术才来是实现
/**
* 【利用反射创建对象】
*/
Class userClassA=User.class;//类名.class获取
Class userClassB=new User().getClass();//通过对象获取class
Class userClassC=Class.forName("com.xdoc.godschool.User");//通过包定位获取class
/**
* 利用无参构造器创建对象
*/
User user=(User)userClassC.newInstance();
/**
* 【获取类的描述信息】
*/
String className=User.class.getSimpleName();
Package packages=User.class.getPackage();
/**
* 【判断class的是否是某些特殊类型】
*/
User.class.isAnnotation();//是否是注解
User.class.isArray();//是否是数组
User.class.isEnum();//是否是枚举
User.class.isInstance(new Object());//是否是某个实例的原类
User.class.isInterface();//是否是接口
User.class.isLocalClass();//是否是本地类型
User.class.isMemberClass();//是否是内部类
User.class.isAnonymousClass();
User.class.isAnnotationPresent(NotNull.class);//是否包含这个注解
/**
* 【获取类的内部单元数组】
* 如果方法名带有Declared则是获取所有,包含父类的
*/
User.class.getFields();//获取所有字段
User.class.getAnnotations();//获取所有注解
User.class.getConstructors();//获取所有构造器
User.class.getMethods();//获取所有方法
User.class.getClasses();//内部类---Class>[]
User.class.getInterfaces();//内部接口--- Class>[]
User.class.getSuperclass();//父类---Class super User>
/**
* 【获取类的内部单元个体】
*/
User.class.getField("age");//按照字段名匹配---Field
User.class.getAnnotation(NotNull.class);//安装注解类型匹配---NotNull
User.class.getConstructor(String.class, Integer.class);//按照参数类型匹配---Constructor
User.class.getMethod("getSome", String.class);//按照方法名+参数类型匹配---Method
/**
* 【Filed类】——找到字段修改值
*/
User user = User.class.newInstance();
Field age = User.class.getField("age");
age.get(user);//class只有类的字节码文件,并不包括实例的地址;所以得把实例传进去;
age.set(user,2);//该某个的实例的age的字段为2
/**
* 【Method类】——利用method执行方法
*/
Method shit = User.class.getMethod("shit");
shit.invoke(user,1,2);
/**
* 【Constructor类】——利用Constructor创造对象
*/
Constructor<User> constructor = User.class.getConstructor();
constructor.newInstance(1,2);
Ps:在反射中我们把所有的对象都抽象成任意类型,所以以一种更灵活的方式去调用方法、修改参数值、调用构造器;在以前非反射编程中往往,这些都是一个具体的属性名、方法名、类名构造器名,但在反射中全部都看成一类东西Filed类、Method类、Constructor类,这种编程方式就叫元编程,可以更大自由度的设计出兼容性更强的框架;
注解能作为一种信息,标记在类、方法或字段上,在反射技术可以读取到这些信息,并利用这些信息对应的实现不同的类型;因此注解通常被用于标记和描述;
注解存活配置:
@Retention(RetentionPolicy.SOURCE)
public @interface MyAnno {
}
类型选择:
@Retention(RetentionPolicy.SOURCE)// 注解将被编译器丢弃
@Retention(RetentionPolicy.CLASS)//注解在class文件中可用,但会被VM丢弃
@Retention( RetentionPolicy.RUNTIME)//VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。
注解规则配置:
@Documented
public @interface MyAnno {
}
类型选择:
@Documented//将此注解包含在 javadoc 中
@Inherited//允许子类继承父类中的注解
@Repeatable//注解可以重复标记
注解用途配置——允许标记在哪里:
@Target({
ElementType.CONSTRUCTOR,//构造器声明
ElementType.FIELD,//域声明(包括 enum 实例)
ElementType.LOCAL_VARIABLE,//局部变量声明
ElementType.METHOD,//方法声明
ElementType.PACKAGE,//包声明
ElementType.PARAMETER,//参数声明
ElementType.TYPE,//类,接口(包括注解类型)或enum声明
})
public @interface MyAnno {
}
注解存储配置——注解存数据:
声明数据属性名,可以给默认值用default 指定
public @interface MyAnno {
public String name() default "";
}
创建注解+注解数据|,利用属性名
public class ResponseVo<T> {
private int code;
@MyAnno(name = "Hello world")
private String message;
private T data;
}
Ps:注解的类型本身和注解内部的数据均可以由反射读到,利用这些完成我们想要的设计!
泛型作为JDK1.5引入的技术,从原理来讲属于编译器上的一种优化,以帮助程序员更好的实现更自由化的编程,比如:
在json返回前端这个过程中,你的返回实体类型肯定是不固定的,这个时候如果你用Obejct替代,势必造成一些代码处理的困难,而泛型允许你用一个变量T替代它,你在外部指定好后,它会为你创建一个匿名内部类来支持你的代码,这就是编译器帮我们做的一些工作,当然还有一些泛型擦除等操作,作为非编译器研究人员这一步我们暂时不必深究,只需要它自动帮我们完成了匿名内部类这一操作实现了任意类型的适配即可,千万不要为源码而源码;
public class ResponseVo<T> {
private int code;
private String message;
private T data;
}
ResponseVo<String> stringResponseVo = new ResponseVo<String>();
注意下面的泛型读取,就是读取接口或者类中固定写死的泛型类型,而不是由泛型变量指定的类型,这是获取不到的
比如fegin接口用于json反序列化时需要自动找到泛型类型
泛型类:
创建对象的时候,类上指定类型,就可以确定属性的类型
public class ResponseVo<T> {
private int code;
private String message;
private T data;
}
ResponseVo<String> stringResponseVo = new ResponseVo<String>();
泛型可以指定多个,比如hashMap
public class HashMap<K,V>
extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable {
}
泛型接口:
实现接口的时候,接口上指定泛型
public interface Generator<T> {
public T next();
}
public class FruitGenerator implements Generator<String> {
private String[] fruits = new String[]{
"Apple", "Banana", "Pear"};
public String next() {
Random rand = new Random();
return fruits[rand.nextInt(3)];
}
}
泛型方法:
public class ResponseVo<T> {
private int code;
private String message;
private T data;
/**
方法泛型在public后面标记类型变量名
* 如果方法泛型和类泛型重名则方法泛型T优先于类的泛型
* 方法泛型的具体类型由实际传入的参数决定
*/
public<T> T print(T ge){
System.out.println(ge.getClass());
return ge;
}
}
public class test01 {
public static void main(String[] args) throws Exception {
ResponseVo<String> stringResponseVo = new ResponseVo<String>();
stringResponseVo.print(1);
}
}
结果:class java.lang.Integer
泛型边界限制:
很显然如果对泛型变量不做任何约束就导致程序无法写下去,所以以下就是约束
变量类型必须是String的子类
public<T extends String> T print(T ge){
System.out.println(ge.getClass());
return ge;
}
String必须是变量的子类
public<String extends T> T print(T ge){
System.out.println(ge.getClass());
return ge;
}
获取泛型类型:
Json序列化中,我们要知道泛型类型则可以完成字段映射,以下方式获取;千万别按照网上那种Type的方式获取,没什么实践意义;
public class ResponseVo<T> {
private int code;
private String message;
private T data;
public ResponseVo(T t){
this.data=t;
}
/**
* 获取字段泛型的类型
*/
public void getFiledGenric() throws Exception{
if(data!=null){
System.out.println(data.getClass());
}
}
/**
* 获取方法泛型的类型
* @param s
* @param
* @throws Exception
*/
public<T> void getMehtodGenric(T s) throws Exception{
if(s!=null){
System.out.println(s.getClass());
}
}
}
测试
public class test01 {
public static void main(String[] args) throws Exception {
ResponseVo<String> stringResponseVo=new ResponseVo<String>("222");
stringResponseVo.getMehtodGenric(1);
stringResponseVo.getFiledGenric();
}
}
结果
class java.lang.Integer
class java.lang.String
泛型可转
如果一个类中某个属性是泛型,那么随着属性的改变这个类的类型会发生变化
responseVOdata的类型一直在发生变化
public class A {
@Data
static class ResponseVO<T> implements Serializable {
private int code;
private String msg;
private T data;
private Long timestamp;
}
public static void main(String[] args) {
ResponseVO responseVO=new ResponseVO();
responseVO.setData("1");
responseVO.setData(2);
}
}
泛型强转
由于ResponseVO未指定泛型,所以泛型的类型可以由左边的引用类型任意指定,此时可以在编译上不至于报错
但是运行时如果我们调用 reponseVO2.getData()并使用String作为引用类型的时候,java编译器会自动做一个强转
所以会报错,因为data此时的类型是Integer类型,编译器自动强转成String肯定报错
public class A {
@Data
static class ResponseVO<T> implements Serializable {
private int code;
private String msg;
private T data;
private Long timestamp;
}
public static ResponseVO createReponse(Object data){
ResponseVO responseVO=new ResponseVO();
responseVO.setData(data);
return responseVO;
}
public static void main(String[] args) {
ResponseVO responseVO=new ResponseVO();
responseVO.setData("1");
System.out.println("执行1");
ResponseVO<String> reponseVO1 = createReponse("");
ResponseVO<String> reponseVO2 = createReponse(1);
String data1 = reponseVO1.getData();
System.out.println("执行2");
String data2 = reponseVO2.getData();
System.out.println("执行3");
}
}
注意泛型处理解决的问题就是,获取某个泛型类或方法在,某段代码(类或接口)里的具体类型,并无法获得原本泛型类的动态类型,永远是T
Type体系中类型的包括:原始类型(Class)、参数化类型(ParameterizedType)、数组类型(GenericArrayType)、类型变量(TypeVariable)、基本类型(Class);Java把这些都统一抽象成Type,也就是说Type比Class更加原生
原始类型
实际就是Class对象,他继承了Type接口(不仅仅包含我们平常所指的类,还包括枚举、数组String[]、注解等)
基本类型
也就是我们所说的java的基本类型,即int,float,double等
泛型参数化类型
返回ParameterizedType,就是我们平常所用到的泛型List、Map
这种;
泛型数组化类型
返回GenericArrayType,是带有泛型的数组,即T[] ;
ParameterizedType接口
public interface ParameterizedType extends Type {
/*
返回参数泛型的内部元素,比如Map,内部元素就是 String\Long
*/
Type[] getActualTypeArguments();
/*
返回泛型的calss
*/
Type getRawType();
Type getOwnerType();
}
实践(1)利用类信息获取泛型
泛型只有是固定的时候,才能利用java原生type去获取,如果泛型是变量T,只能在运行时利用对象.class去获取类型
@Slf4j
public class JavaType_Test01 {
static class ResposneVO<String,Long>{
private List<Integer> stringData;
private Map<String,Long> mapData;
public <T> void print(List<String> param1,List<T> param2 ){
}
}
public static void main(String[] args) {
/**
* @类中字段上的泛型
*/
Field[] fields = ResposneVO.class.getDeclaredFields();
for(Field filed:fields){
Type filedPackType = filed.getGenericType();
if(filedPackType instanceof ParameterizedType){
Type[] filedElementTypes =((ParameterizedType) filedPackType).getActualTypeArguments();;
log.info("【字段名】"+filed.getName());
log.info("(1)字段泛型整体:"+filedPackType.toString());
log.info("(2)字段泛型元素:"+Arrays.toString(filedElementTypes));
log.info("————————————————");
}
}
/**
* @类中方法上的泛型
*/
Method[] methods = ResposneVO.class.getDeclaredMethods();
for(Method method:methods){
log.info("【方法名】:"+method.getName());
Parameter[] parameters = method.getParameters();
for(Parameter parameter:parameters){
Type methodParamPackType = parameter.getParameterizedType();
if(methodParamPackType instanceof ParameterizedType){
Type[] methodParamElementTypes =((ParameterizedType) methodParamPackType).getActualTypeArguments();;
log.info("(1)参数名:"+parameter.getName());
log.info("(2)参数泛型整体:"+Arrays.toString(methodParamElementTypes));
log.info("(3)参数泛型元素:"+Arrays.toString(methodParamElementTypes));
log.info("***********");
}
}
log.info("————————————————");
Type genericSuperclass = ResposneVO.class.getGenericSuperclass();
if (genericSuperclass instanceof ParameterizedType) {
System.out.println("父类是一个参数化类型,类型名称为:" + genericSuperclass.getTypeName());
}
}
}
}
15:41:55.684 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - 【字段名】stringData
15:41:55.686 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - (1)字段泛型整体:java.util.List<java.lang.Integer>
15:41:55.687 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - (2)字段泛型元素:[class java.lang.Integer]
15:41:55.687 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - ————————————————
15:41:55.687 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - 【字段名】mapData
15:41:55.687 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - (1)字段泛型整体:java.util.Map<String, Long>
15:41:55.687 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - (2)字段泛型元素:[String, Long]
15:41:55.687 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - ————————————————
15:41:55.687 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - 【方法名】:print
15:41:55.688 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - (1)参数名:param1
15:41:55.688 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - (2)参数泛型整体:[String]
15:41:55.688 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - (3)参数泛型元素:[String]
15:41:55.688 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - ***********
15:41:55.688 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - (1)参数名:param2
15:41:55.688 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - (2)参数泛型整体:[T]
15:41:55.688 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - (3)参数泛型元素:[T]
15:41:55.688 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - ***********
15:41:55.688 [main] INFO com.xdoc.template.module.test_type.JavaType_Test01 - ————————————————
Process finished with exit code 0
实践(2)利用接口信息获取泛型
比用Fegin定义的接口,编解码器反序列化的时候可以根据接口指定的类型泛型反序列化
@Slf4j
public class JavaType_Test02 {
static class ResposneVO<T> {
int code;
T data;
String msg;
}
static interface UserConsumer {
ResposneVO<String> getUsers();
}
public static void main(String[] args) {
Method[] methods =UserConsumer.class.getDeclaredMethods();
for (Method method : methods) {
log.info("【方法名】:" + method.getName());
Type returnPackType = method.getGenericReturnType();
if(returnPackType instanceof ParameterizedType){
Type[] returnElementTypes =((ParameterizedType) returnPackType).getActualTypeArguments();;
log.info("(1)返回值泛型整体:"+Arrays.toString(returnElementTypes));
log.info("(2)返回值泛型元素:"+Arrays.toString(returnElementTypes));
}
}
}
}
15:43:44.100 [main] INFO com.xdoc.template.module.test_type.JavaType_Test02 - 【方法名】:getUsers
15:43:44.104 [main] INFO com.xdoc.template.module.test_type.JavaType_Test02 - (1)返回值泛型整体:[class java.lang.String]
15:43:44.105 [main] INFO com.xdoc.template.module.test_type.JavaType_Test02 - (2)返回值泛型元素:[class java.lang.String]
注意首先必须是参数化泛型类型,然后才能找到进一步明确是不是变量泛型
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
Type[] getBounds();// 获取泛型的边界
D getGenericDeclaration();// 获取申明所在的具体对象
String getName();// 获取具体类型变量的名称
AnnotatedType[] getAnnotatedBounds();// 获取类型变量边界上添加的注解
}
@Slf4j
public class JavaType_Test03 {
static class ResposneVO<T,Q> {
int code;
T data;
String msg;
}
static interface UserConsumer {
<T extends String, Q extends Integer> ResposneVO<T,Q> getUsers ();
<T extends String,Q> ResposneVO<T,Q> getApprovers ();
}
public static void main(String[] args) {
Method[] methods =UserConsumer.class.getDeclaredMethods();
for (Method method : methods) {
log.info("【方法名】:" + method.getName());
Type returnPackType = method.getGenericReturnType();
if(returnPackType instanceof ParameterizedType){
ParameterizedType returnPackType_Parma=((ParameterizedType) returnPackType);
log.info(((Class)returnPackType_Parma.getRawType()).getName());
log.info(((Class)returnPackType_Parma.getOwnerType()).getName());
Type[] returnElementTypes =((ParameterizedType) returnPackType).getActualTypeArguments();;
log.info("(1)返回值泛型整体:"+Arrays.toString(returnElementTypes));
log.info("(2)返回值泛型元素:"+Arrays.toString(returnElementTypes));
/**
* 多个泛型时需要遍历寻找
*/
for(Type returnElementType:returnElementTypes){
if(returnElementType instanceof TypeVariable){
log.info("(3)返回值泛型元素包含了一个泛型边界");
TypeVariable returnElementType_variable=((TypeVariable) returnElementType);
log.info("类型:{}",returnElementType_variable.getName());
log.info("边界:{}",Arrays.toString(returnElementType_variable.getAnnotatedBounds()));
log.info("类型:{}",returnElementType_variable.getBounds());
log.info("描述:{}",returnElementType_variable.getGenericDeclaration());
}
}
}
}
}
}
17:02:25.137 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 【方法名】:getApprovers
17:02:25.143 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - com.xdoc.template.module.test_type.JavaType_Test03$ResposneVO
17:02:25.144 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - com.xdoc.template.module.test_type.JavaType_Test03
17:02:25.144 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - (1)返回值泛型整体:[T, Q]
17:02:25.144 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - (2)返回值泛型元素:[T, Q]
17:02:25.144 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - (3)返回值泛型元素包含了一个泛型边界
17:02:25.144 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 类型:T
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 边界:[sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@2d363fb3]
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 类型:class java.lang.String
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 描述:public abstract com.xdoc.template.module.test_type.JavaType_Test03$ResposneVO com.xdoc.template.module.test_type.JavaType_Test03$UserConsumer.getApprovers()
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - (3)返回值泛型元素包含了一个泛型边界
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 类型:Q
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 边界:[sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@7d6f77cc]
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 类型:class java.lang.Object
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 描述:public abstract com.xdoc.template.module.test_type.JavaType_Test03$ResposneVO com.xdoc.template.module.test_type.JavaType_Test03$UserConsumer.getApprovers()
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 【方法名】:getUsers
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - com.xdoc.template.module.test_type.JavaType_Test03$ResposneVO
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - com.xdoc.template.module.test_type.JavaType_Test03
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - (1)返回值泛型整体:[T, Q]
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - (2)返回值泛型元素:[T, Q]
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - (3)返回值泛型元素包含了一个泛型边界
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 类型:T
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 边界:[sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@5aaa6d82]
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 类型:class java.lang.String
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 描述:public abstract com.xdoc.template.module.test_type.JavaType_Test03$ResposneVO com.xdoc.template.module.test_type.JavaType_Test03$UserConsumer.getUsers()
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - (3)返回值泛型元素包含了一个泛型边界
17:02:25.146 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 类型:Q
17:02:25.147 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 边界:[sun.reflect.annotation.AnnotatedTypeFactory$AnnotatedTypeBaseImpl@73a28541]
17:02:25.147 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 类型:class java.lang.Integer
17:02:25.147 [main] INFO com.xdoc.template.module.test_type.JavaType_Test03 - 描述:public abstract com.xdoc.template.module.test_type.JavaType_Test03$ResposneVO com.xdoc.template.module.test_type.JavaType_Test03$UserConsumer.getUsers()
Process finished with exit code 0
public interface WildcardType extends Type {
Type[] getUpperBounds(); // 获取通配符表达式的上界
Type[] getLowerBounds();// 获取通配符表达式的下界
}
@Slf4j
public class JavaType_Test04 {
static class ResposneVO<T> {
int code;
T data;
String msg;
}
static interface UserConsumer {
ResposneVO<? extends String> getUsers();
ResposneVO<? super String > getAprrovers();
}
public static void main(String[] args) {
Method[] methods =UserConsumer.class.getDeclaredMethods();
for (Method method : methods) {
log.info("【方法名】:" + method.getName());
Type returnPackType = method.getGenericReturnType();
if(returnPackType instanceof ParameterizedType){
ParameterizedType returnPackType_Parma=((ParameterizedType) returnPackType);
log.info(((Class)returnPackType_Parma.getRawType()).getName());
log.info(((Class)returnPackType_Parma.getOwnerType()).getName());
Type[] returnElementTypes =((ParameterizedType) returnPackType).getActualTypeArguments();;
log.info("(1)返回值泛型整体:"+Arrays.toString(returnElementTypes));
log.info("(2)返回值泛型元素:"+Arrays.toString(returnElementTypes));
/**
* 多个泛型时需要遍历寻找
*/
for(Type returnElementType:returnElementTypes) {
if (returnElementType instanceof TypeVariable) {
log.info("(3)返回值泛型元素包含了一个泛型边界");
TypeVariable returnElementType_variable = ((TypeVariable) returnElementType);
log.info("类型:", returnElementType_variable.getName());
log.info("边界:", Arrays.toString(returnElementType_variable.getAnnotatedBounds()));
log.info("类型:", returnElementType_variable.getBounds());
log.info("描述:", returnElementType_variable.getGenericDeclaration());
} else if (returnElementType instanceof WildcardType) {
// 同时List又是一个参数化类型,而T又是一个类型变量
log.info("(3)返回值泛型元素包含了一个通配符泛型");
Type[] lowerBounds = ((WildcardType) returnElementType).getLowerBounds();
Type[] upperBounds = ((WildcardType) returnElementType).getUpperBounds();
/**
* 处理上通配符
*/
for (Type lowerBound : upperBounds) {
/**
* 直接是原始类型强转成Class
*/
if(lowerBound instanceof Class ){
log.info("下边界:{}",((Class)(lowerBound)).getName());
}
/**
* 如果又是参数泛型则要拆解
*/
else if (lowerBound instanceof ParameterizedType) {
System.out.println("参数化类型的名称为:" + lowerBound.getTypeName());
Type[] actualTypeArguments1 = ((ParameterizedType) lowerBound).getActualTypeArguments();
for (Type type : actualTypeArguments1) {
if (type instanceof TypeVariable) {
String name = ((TypeVariable) type).getName();
System.out.println("类型变量名称为:" + name);
}
}
}
}
/**
* 处理下通配符
*/
for (Type upperBound : lowerBounds) {
/**
* 直接是原始类型强转成Class
*/
if(upperBound instanceof Class ){
log.info("上边界:{}",((Class)(upperBound)).getName());
}
/**
* 如果又是参数泛型则要拆解
*/
else if (upperBound instanceof ParameterizedType) {
System.out.println("参数化类型的名称为:" + upperBound.getTypeName());
Type[] actualTypeArguments1 = ((ParameterizedType) upperBound).getActualTypeArguments();
for (Type type : actualTypeArguments1) {
if (type instanceof TypeVariable) {
String name = ((TypeVariable) type).getName();
System.out.println("类型变量名称为:" + name);
}
}
}
}
}
}
}
}
}
}
17:03:59.721 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - 【方法名】:getAprrovers
17:03:59.730 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - com.xdoc.template.module.test_type.JavaType_Test04$ResposneVO
17:03:59.731 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - com.xdoc.template.module.test_type.JavaType_Test04
17:03:59.731 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - (1)返回值泛型整体:[? super java.lang.String]
17:03:59.731 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - (2)返回值泛型元素:[? super java.lang.String]
17:03:59.731 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - (3)返回值泛型元素包含了一个通配符泛型
17:03:59.731 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - 下边界:java.lang.Object
17:03:59.733 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - 上边界:java.lang.String
17:03:59.733 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - 【方法名】:getUsers
17:03:59.733 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - com.xdoc.template.module.test_type.JavaType_Test04$ResposneVO
17:03:59.733 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - com.xdoc.template.module.test_type.JavaType_Test04
17:03:59.734 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - (1)返回值泛型整体:[? extends java.lang.String]
17:03:59.734 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - (2)返回值泛型元素:[? extends java.lang.String]
17:03:59.734 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - (3)返回值泛型元素包含了一个通配符泛型
17:03:59.734 [main] INFO com.xdoc.template.module.test_type.JavaType_Test04 - 下边界:java.lang.String
处理type类型时,往往递归进行下去的,如果是Class对象直接输出,如果是参数化则要继续拆解内部的type直到变成Class为止;记住Class也是实现了Type接口;
Type体系中类型的包括:原始类型(Class)、参数化类型(ParameterizedType)、数组类型(GenericArrayType)、类型变量(TypeVariable)、基本类型(Class);
原始类型
实际就是Class对象,他继承了Type接口(不仅仅包含我们平常所指的类,还包括枚举、数组String[]、注解等)
基本类型
返回一个值,也就是我们所说的java的基本类型,即int,float,double等
泛型参数化类型
返回ParameterizedType,就是我们平常所用到的泛型List、Map
这种;
泛型数组化类型
返回GenericArrayType,是带有泛型的数组,即T[] ;