Java反射通过class获取父类泛型类型

Java反射通过class获取父类泛型类型

在Java的反射技术中,通过Method和Field对象很容易就可以取出泛型类型的具体类型。但是普通类的泛型参数在编译期会被擦除,比如定义了一个List<String>对象,在运行期我们可以拿到的信息就只剩下List,并不知道List中的元素类型是什么。这也说明了,为什么fun(List<String> list)和 fun(List<Integer>)会被编译器认为是相同的函数。
但是,对于获取父类的泛型类型,还是会有办法的。在Class类中,有这样一个方法:
    /**
     * Returns the {@code Type} representing the direct superclass of
     * the entity (class, interface, primitive type or void) represented by
     * this {@code Class}.
     *
     * <p>If the superclass is a parameterized type, the {@code Type}
     * object returned must accurately reflect the actual type
     * parameters used in the source code. The parameterized type
     * representing the superclass is created if it had not been
     * created before. See the declaration of {@link
     * java.lang.reflect.ParameterizedType ParameterizedType} for the
     * semantics of the creation process for parameterized types.  If
     * this {@code Class} represents either the {@code Object}
     * class, an interface, a primitive type, or void, then null is
     * returned.  If this object represents an array class then the
     * {@code Class} object representing the {@code Object} class is
     * returned.
     *
     * @throws java.lang.reflect.GenericSignatureFormatError if the generic
     *     class signature does not conform to the format specified in
     *     <cite>The Java™ Virtual Machine Specification</cite>
     * @throws TypeNotPresentException if the generic superclass
     *     refers to a non-existent type declaration
     * @throws java.lang.reflect.MalformedParameterizedTypeException if the
     *     generic superclass refers to a parameterized type that cannot be
     *     instantiated  for any reason
     * @return the superclass of the class represented by this object
     * @since 1.5
     */
    public Type getGenericSuperclass() {
        if (getGenericSignature() != null) {
            // Historical irregularity:
            // Generic signature marks interfaces with superclass = Object
            // but this API returns null for interfaces
            if (isInterface())
                return null;
            return getGenericInfo().getSuperclass();
        } else
            return getSuperclass();
    }
        此方法返回的是具有泛型信息的父类,如果没有则返回Object对象。具体什么样的类都返回什么样的结果,来看测试代码
    public void printGenericType(){
        Class clazz1 = new ArrayList<Integer>().getClass();
        Class clazz2 = new String[0].getClass();
        Class clazz3 = String.class;
        Class clazz4 = Object.class;
        Class clazz5 = new IntList().getClass();

        System.out.println(clazz1.getGenericSuperclass());
        System.out.println(clazz2.getGenericSuperclass());
        System.out.println(clazz3.getGenericSuperclass());
        System.out.println(clazz4.getGenericSuperclass());
        System.out.println(clazz5.getGenericSuperclass());
    }
结果:
java.util.AbstractList<E>
class java.lang.Object
class java.lang.Object
null
java.util.ArrayList<java.lang.Integer>
          上面的测试代码中分别打印出了ArrayList,数组,普通类,Object类和自定义的一个类通过getGenericSuperclass()方法获取到的结果。普通类以及数组的父类都是Object,所以打印出的结果是Object。Object没有父类,打印出的是null。普通的ArrayList打印出的结果是java.util.AbstractList<E>,第五个class打印出了带有泛型信息的java.util.ArrayList<java.lang.Integer>。IntList的定义是这样的
public class IntList extends ArrayList<Integer> {
}
ArrayList的定义是这样的
public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
        两处的不同在于继承父类的时候有没有知道父类泛型的具体类型,如果指定了,则可以通过上面的方法得到这个具体的类型。否则不能得到,这两者一定还存在 其他的区别联系,下面打印出获得的具体类型是什么
    public void getGenericType(){
        Class clazz1 = new ArrayList<Integer>().getClass();
        Type type = clazz1.getGenericSuperclass();
        ParameterizedType parameterizedType = (ParameterizedType) type;
        System.out.println(parameterizedType);
        System.out.println(parameterizedType.getActualTypeArguments()[0].getClass());

        Class clazz2 = new IntList().getClass();
        Type type2 = clazz2.getGenericSuperclass();
        ParameterizedType parameterizedType2 = (ParameterizedType) type2;
        System.out.println(parameterizedType2);
        System.out.println(parameterizedType2.getActualTypeArguments()[0].getClass());
    }
结果
java.util.AbstractList<E>
class sun.reflect.generics.reflectiveObjects.TypeVariableImpl
java.util.ArrayList<java.lang.Integer>
class java.lang.Class
       原来如此,如果在继承父类的时候没有指定父类的泛型类型,则这时候获取到的类型是TypeVariableImpl;而指定了父类的泛型类型则这时候就能获取到对应的Class



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值