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

来源:互联网 发布:淘宝店铺客户流失分析 编辑:程序博客网 时间:2024/04/30 21:35

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

抽象类和接口各不相同。

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