java在运行时获取泛型实例的方法

如题,有时候我们在接口中或者是抽象类使用泛型来适应子类不同的类型,可是当我们需要拿到泛型实例或者泛型类型的时候,可以这样去得到:

抽象类和接口各不相同。

  • 抽象类获取泛型实例的方法
Class<?> aClass = obj.getClass();//先得到类的字节码
Type genericSuperclass = aClass.getGenericSuperclass();// 返回超类的type
ParameterizedType types = (ParameterizedType) genericSuperclass;// 如果超类是参数化类型,返回的Type对象必须准确地反映源代码中使用的实际类型参数,也就是 ParameterizedType 类型
Type[] actualTypeArguments =  types.getActualTypeArguments();//返回表示此类型的实际类型参数的Type对象的数组。请注意,在某些情况下,返回的数组是空的。如果此类型表示嵌套在参数化类型中的非参数化类型,则会发生这种情况。
Class<T> reponseClass = (Class) actualTypeArguments[0];
  • 接口获取泛型实例的方法
Class<?> aClass = obj.getClass();//先得到类的字节码
/*
返回表示由此对象表示的类或接口直接实现的接口的类型。
如果超级接口是一个参数化类型,返回的Type对象必须准确地反映源代码中使用的实际类型参数。代表每个超级界面的参数化类型是在之前没有创建的情况下创建的。有关参数化类型的创建过程的语义,请参阅ParameterizedType的声明。
如果此对象表示一个类,则返回值是一个包含表示由类实现的所有接口的对象的数组。数组中接口对象的顺序对应于该对象表示的类的声明的implements子句中的接口名称的顺序。在数组类中,接口Cloneable和Serializable按照这个顺序返回。
如果此对象表示一个接口,则该数组包含表示由该接口直接扩展的所有接口的对象。数组中接口对象的顺序对应于该对象表示的接口声明的extends子句中接口名称的顺序。
如果此对象表示不实现接口的类或接口,则该方法返回长度为0的数组。
如果这个对象表示一个原始类型或void,则该方法返回一个长度为0的数组。
* */
Type[] types = aClass.getGenericInterfaces();
ParameterizedType parameterizedType = (ParameterizedType) types[0];
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
Class<T> reponseClass = (Class) actualTypeArguments[0];

最后附上完整工具类代码:

/**
 * 运行时获取泛型类型
 */
public class GenericUtil {
    public static <T> T getSuperclassType(Object obj, int i) {
        try {
            Class<?> aClass = obj.getClass();//先得到类的字节码
            Type genericSuperclass = aClass.getGenericSuperclass();
            if (genericSuperclass instanceof ParameterizedType) {
                ParameterizedType types = (ParameterizedType) genericSuperclass;//抽象类
                Type[] actualTypeArguments = types.getActualTypeArguments();
                Class<T> reponseClass = (Class) actualTypeArguments[i];
                return reponseClass.newInstance();
            } else {
                return null;
            }
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static <T> T getInterfaceType(Object obj, int i) {
        try {
            Class<?> aClass = obj.getClass();//先得到类的字节码
                /*
                返回表示由此对象表示的类或接口直接实现的接口的类型。
                如果超级接口是一个参数化类型,返回的Type对象必须准确地反映源代码中使用的实际类型参数。代表每个超级界面的参数化类型是在之前没有创建的情况下创建的。有关参数化类型的创建过程的语义,请参阅ParameterizedType的声明。
                如果此对象表示一个类,则返回值是一个包含表示由类实现的所有接口的对象的数组。数组中接口对象的顺序对应于该对象表示的类的声明的implements子句中的接口名称的顺序。在数组类中,接口Cloneable和Serializable按照这个顺序返回。
                如果此对象表示一个接口,则该数组包含表示由该接口直接扩展的所有接口的对象。数组中接口对象的顺序对应于该对象表示的接口声明的extends子句中接口名称的顺序。
                如果此对象表示不实现接口的类或接口,则该方法返回长度为0的数组。
                如果这个对象表示一个原始类型或void,则该方法返回一个长度为0的数组。
                * */
            Type[] types = aClass.getGenericInterfaces();
            ParameterizedType parameterizedType = (ParameterizedType) types[0];
            Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
            Class<T> reponseClass = (Class) actualTypeArguments[i];
            return reponseClass.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Class<?> forName(String className) {
        try {
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,805评论 18 399
  • Kotlin 知识梳理系列文章 Kotlin 知识梳理(1) - Kotlin 基础Kotlin 知识梳理(2) ...
    泽毛阅读 2,583评论 0 4
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 7,147评论 0 62
  • 在经过一次没有准备的面试后,发现自己虽然写了两年的android代码,基础知识却忘的差不多了。这是程序员的大忌,没...
    猿来如痴阅读 2,898评论 3 10
  • 接口/抽象类意义规范、扩展、回调为其子类提供一个公共的类型 封装子类中得重复内容 定义抽象方法,子类虽然有不同的实...
    MigrationUK阅读 2,212评论 1 28