美文网首页kankan(good)
反射工具类:获取到泛型对象的泛型类型

反射工具类:获取到泛型对象的泛型类型

作者: 小胖学编程 | 来源:发表于2023-01-17 13:11 被阅读0次

工具类:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 泛型工具类,用于获取类对象绑定的泛型参数
 * @author skyfalling
 * @version 1.0.0
 */
public class Generics {

  /**
   * 查找类对象clazz绑定的genericClass声明的泛型参数
   *
   * @param clazz        绑定泛型参数的类
   * @param genericClass 声明泛型的类
   * @param index        泛型在声明类中的索引位置
   * @return 如果绑定了泛型参数, 则返回泛型类型, 否则返回null
   */
  public static Class find(Class clazz, Class genericClass, int index) {
    if (!genericClass.isAssignableFrom(clazz)) {
      return null;
    }
    List<Type> types = getGenericTypes(clazz);
    for (Type type : types) {
      Class genericType = find(type, genericClass, index);
      if (genericType != null) {
        return genericType;
      }
    }
    return null;
  }

  /**
   * 查找类type上绑定的genericClass声明的泛型类型
   *
   * @param type         泛型对象
   * @param genericClass 声明泛型的类
   * @param index        泛型在声明类中的索引位置
   * @return
   */
  private static Class find(Type type, Class genericClass, int index) {
    if (type instanceof Class) {
      return find((Class) type, genericClass, index);
    }
    if (type instanceof ParameterizedType) {
      ParameterizedType pType = (ParameterizedType) type;
      Type rawType = pType.getRawType();
      if (rawType instanceof Class) {
        Class rawClass = (Class) rawType;
        if (rawClass == genericClass) {
          Type realType = pType.getActualTypeArguments()[index];
          if (realType instanceof Class) {
            return (Class) realType;
          } else if (realType instanceof ParameterizedType) {
            //这里是泛型的泛型
            return (Class) ((ParameterizedType) realType).getRawType();
          }
        } else if (genericClass.isAssignableFrom(rawClass)) {
          Map<String, Type> map = combine(pType.getActualTypeArguments(), rawClass);
          return find(rawClass, genericClass, index, map);
        }
      }
    }
    return null;
  }

  /**
   * 查找类currentClass上绑定的genericClass声明的泛型类型
   *
   * @param currentClass 绑定泛型参数的类
   * @param genericClass 声明泛型的类
   * @param index        泛型在声明类中的索引位置
   * @param typeMap      已绑定的泛型类型映射表
   * @return
   */
  private static Class find(Class currentClass, Class genericClass, int index, Map<String, Type> typeMap) {
    List<Type> types = getGenericTypes(currentClass);
    for (Type type : types) {
      if (type instanceof ParameterizedType) {
        ParameterizedType pType = (ParameterizedType) type;
        Type rawType = pType.getRawType();
        if (rawType instanceof Class) {
          Class rawClass = (Class) rawType;
          Map<String, Type> map = transfer(pType, typeMap);
          Type[] typeArray = map.values().toArray(new Type[0]);
          if (rawClass == genericClass) {
            Type realType = typeArray[index];
            if (realType instanceof Class) {
              return (Class) realType;
            } else if (realType instanceof ParameterizedType) {
              //这里是泛型的泛型
              return (Class) ((ParameterizedType) realType).getRawType();
            }
          } else if (genericClass.isAssignableFrom(rawClass)) {
            return find(rawClass, genericClass, index, combine(typeArray, rawClass));
          }
        }
      }
    }
    return null;
  }


  /**
   * 获取当前类继承的父类和实现接口的泛型列表
   *
   * @param clazz
   * @return
   */
  private static List<Type> getGenericTypes(Class clazz) {
    if (clazz == Object.class) {
      return Collections.EMPTY_LIST;
    }
    List<Type> list = new ArrayList<>();
    Type[] types = clazz.getGenericInterfaces();
    for (Type type : types) {
      list.add(type);
    }
    list.add(clazz.getGenericSuperclass());
    return list;
  }

  /**
   * 构建泛型映射表
   *
   * @param typeArguments 泛型参数
   * @param rawClass      声明泛型的类
   * @return
   */
  private static Map<String, Type> combine(Type[] typeArguments, Class rawClass) {
    Map<String, Type> map = new LinkedHashMap<>(typeArguments.length);
    TypeVariable[] typeParameters = rawClass.getTypeParameters();
    for (int i = 0; i < typeParameters.length; i++) {
      map.put(typeParameters[i].getName(), typeArguments[i]);
    }
    return map;
  }


  /**
   * 转换泛型映射表
   *
   * @param parameterizedType 绑定参数类型的泛型对象
   * @param typeMap           已绑定的泛型类型映射表
   * @return
   */
  private static Map<String, Type> transfer(ParameterizedType parameterizedType, Map<String, Type> typeMap) {

    Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
    TypeVariable[] typeParameters = ((Class) parameterizedType.getRawType()).getTypeParameters();
    Map<String, Type> map = new LinkedHashMap<>();
    for (int i = 0; i < actualTypeArguments.length; i++) {
      Type type = actualTypeArguments[i];
      if (type instanceof TypeVariable) {
        String variableName = ((TypeVariable) type).getName();
        map.put(variableName, typeMap.get(variableName));
      } else {
        map.put(typeParameters[i].getName(), type);
      }
    }
    return map;
  }
}

使用方式:

定义泛型接口:

public interface Node<T, R> {
    R execute(T param);

    default Class<T> paramType() {
        return Generics.find(this.getClass(), Node.class, 0);
    }
}

定义泛型类:

public class MyNode implements Node<String, User> {
    @Override
    public User execute(String param) {

        Class<String> stringClass = paramType();

        System.out.println(stringClass);

        return null;
    }

    public static void main(String[] args) {
        MyNode myNode=new MyNode();
        myNode.execute("123");
    }

附录

代码来源的git地址

相关文章

  • 反射工具类:获取到泛型对象的泛型类型

    工具类: 使用方式: 定义泛型接口: 定义泛型类: 附录 代码来源的git地址[https://github.co...

  • Java 完美获取泛型类型(包含嵌套的泛型)

    完美获取泛型类型(包含嵌套多层的泛型) 1. 工具类 获取泛型类型工具类 2. 使用方法 2.1. 集成接口带有泛...

  • 章节笔记——泛型与反射机制

    泛型 反射机制 泛型:由于类型转换错误,编译时不报错,运行时报错。为了弥补这个问题,用泛型弥补,集合类添加对象不需...

  • 泛型和反射在项目中的基本应用之一

    一般在抽取的公共类中会涉及到泛型,而泛型的类型需要用到反射类中的方法确定泛型类型。

  • 泛型 & 注解 & Log4J日志组件

    掌握的知识 : 基本用法、泛型擦除、泛型类/泛型方法/泛型接口、泛型关键字、反射泛型(案例) 泛型 概述 : 泛型...

  • 泛型类

    注意:泛型类型必须是引用类型 泛型类,把泛型定义在类上 格式:public class 类名<泛型类型1,…> 把...

  • typescript入门-泛型

    基础定义 泛型接口 泛型类 泛型约束 使用类类型

  • Java 19-5.1泛型

    泛型类定义泛型类可以规定传入对象 泛型类 和泛型方法 泛型接口 如果实现类也无法确定泛型 可以在继承类中确定泛型:

  • 泛型程序

    一、泛型类 二、泛型方法 三、 类型变量的限定 方法内部有需要创建对象调用方法的,因为泛型类型变量T可以是任何对象...

  • OC 泛型, __kindof

    泛型:限制类型 泛型声明格式:在声明类的时候,在类型后面<泛型名称>泛型定义格式:放在限制的类型后面<类型> 泛型...

网友评论

    本文标题:反射工具类:获取到泛型对象的泛型类型

    本文链接:https://www.haomeiwen.com/subject/mfgthdtx.html