java 运行时获取泛型真实类型

前情提要

本文章用于运行时获取泛型的具体类型,有一些情况下可以获取到真实类型,有一些情况下获取不到的情况。
Class 类的两个方法

	/**
     * Returns the {@code Class} representing the superclass of the entity
     * (class, interface, primitive type or void) represented by this
     * {@code Class}.  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.
     *
     * @return the superclass of the class represented by this object.
     * 用于获取this指代的对象的父类的类型,如果this指代的对象类型是Object,接口,基本类型,或void,方法返回null
     * 如果this指代的是一个数组,则返回Object类型
     * 这个方法会做泛型擦除,我们获取不到真实声明的泛型,我们要用下面的那个方法
     */
    public native Class<? super T> getSuperclass();
    /**
     * 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&trade; 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
     * 获取this对象的源代码中声明的父类类型,包括声明的泛型,即泛型未被擦除
     * 我们的测试需要使用这个方法
     */
    public Type getGenericSuperclass() {
        ClassRepository info = getGenericInfo();
        if (info == null) {
            return getSuperclass();
        }

        // Historical irregularity:
        // Generic signature marks interfaces with superclass = Object
        // but this API returns null for interfaces
        if (isInterface()) {
            return null;
        }

        return info.getSuperclass();
    }

测试代码

public class Main {
    public static void main(String[] args) {
        // TODO: 普通类继承抽象类  1=10
        //带body实现和泛型指定
        Type list1 = new ArrayList<String>() {
        }.getClass().getGenericSuperclass();
        //带泛型不带body
        Type list2 = new ArrayList<String>().getClass().getGenericSuperclass();
        //带body不带泛型,编译报错 Cannot use "<>"with anonymous inner classes
        //Type list3 = new ArrayList<>() {
        //}.getClass().getGenericSuperclass();
        //什么都不带
        Type list4 = new ArrayList<>().getClass().getGenericSuperclass();


        // TODO: 接口  2=3
        //带body实现和泛型指定
        Type a1 = new Aoo<Double>() {
        }.getClass().getGenericSuperclass();
        //带泛型不带body 编译报错 'Aoo' is abstract; cannot be instantiated
        //Type a2 = new Aoo<Double>().getClass().getGenericSuperclass();
        //带body不带泛型 编译报错 Cannot use "<>"with anonymous inner classes
        //Type a3 = new Aoo<>() {
        //}.getClass().getGenericSuperclass();


        // TODO: 接口继承接口  3=2
        //带body实现和泛型指定
        Type c1 = new Coo<String>() {
        }.getClass().getGenericSuperclass();
        //带泛型不带body 编译报错 'Coo' is abstract; cannot be instantiated
        //Type c2 = new Coo<Double>().getClass().getGenericSuperclass();
        //带body不带泛型 编译报错 Cannot use "<>"with anonymous inner classes
        //Type c3 = new Coo<>() {
        //}.getClass().getGenericSuperclass();


        // TODO: 普通类实现接口  4=9
        //带body实现和泛型指定
        Type b1 = new Boo<Double>() {
        }.getClass().getGenericSuperclass();
        //带泛型不带body
        Type b2 = new Boo<String>().getClass().getGenericSuperclass();
        //带body不带泛型,编译报错 Cannot use "<>"with anonymous inner classes
        //Type b3 = new Boo<>(){}.getClass().getGenericSuperclass();
        //什么都不带
        Type b4 = new Boo<>().getClass().getGenericSuperclass();


        // TODO: 抽象类  5=6=7=8
        //带body实现和泛型指定
        Type foo1 = new Foo<String>() {
        }.getClass().getGenericSuperclass();
        //带泛型不带body 编译报错  'Foo' is abstract; cannot be instantiated
        //Type foo2=new Foo<String>().getClass().getGenericSuperclass();
        //带body不带泛型 编译报错 Cannot use "<>"with anonymous inner classes
        //Type foo3=new Foo<>(){}.getClass().getGenericSuperclass();


        //TODO: 抽象类继承普通类  6=5=7=8
        //带body实现和泛型指定
        Type t1 = new Too<String>() {
        }.getClass().getGenericSuperclass();
        //带泛型不带body 'Too' is abstract; cannot be instantiated
        //Type t2 = new Too<String>().getClass().getGenericSuperclass();
        //带body不带泛型,编译报错 Cannot use "<>"with anonymous inner classes
        //Type t3 = new Too<>() {
        //}.getClass().getGenericSuperclass();


        // TODO: 抽象类继承抽象类  7=5=6=8
        //带body实现和泛型指定
        Type rpc1 = new QueueRpcSupport<String>() {
        }.getClass().getGenericSuperclass();
        //带泛型不带body 编译报错  'QueueRpcSupport' is abstract; cannot be instantiated
        //Type rpc2 = new QueueRpcSupport<String>().getClass().getGenericSuperclass();
        //带body不带泛型 编译报错 Cannot use "<>"with anonymous inner classes
        //Type rpc3 = new QueueRpcSupport<>() {
        //}.getClass().getGenericSuperclass();


        // TODO: 抽象类实现接口  8=5=6=7
        //带body实现和泛型指定
        Type d1 = new Doo<Double>() {
        }.getClass().getGenericSuperclass();
        //带泛型不带body 'Doo' is abstract; cannot be instantiated
        //Type d2 = new Doo<String>().getClass().getGenericSuperclass();
        //带body不带泛型,编译报错 Cannot use "<>"with anonymous inner classes
        //Type d3 = new Doo<>(){}.getClass().getGenericSuperclass();


        // TODO: 普通类  9=4
        //带body实现和泛型指定
        Type z1 = new Zoo<String>() {
        }.getClass().getGenericSuperclass();
        //带泛型不带body
        Type z2 = new Zoo<String>().getClass().getGenericSuperclass();
        //带body不带泛型,编译报错 Cannot use "<>"with anonymous inner classes
        //Type z3 = new Zoo<>() {
        //}.getClass().getGenericSuperclass();
        //什么都不带
        Type z4 = new Zoo<>().getClass().getGenericSuperclass();


        // TODO: 2022/3/18 普通类继承普通类  10=1
        //带body实现和泛型指定
        Type x1 = new Xoo<String>() {
        }.getClass().getGenericSuperclass();
        //什么都不带
        Type x2 = new Xoo<>().getClass().getGenericSuperclass();
        //带body不带泛型,编译报错 Cannot use "<>"with anonymous inner classes
        //Type x3 = new Xoo<>() {
        //}.getClass().getGenericSuperclass();
        //带泛型不带body
        Type x4 = new Xoo<String>().getClass().getGenericSuperclass();
        System.out.println("test");


    }
}

//接口
interface Aoo<E> {
}

//接口继承接口
interface Coo<E> extends Aoo<E> {
}

//抽象类
abstract class Foo<T> {
}

//抽象类实现接口
abstract class Doo<E> implements Coo<E> {

}

//抽象类继承抽象类
abstract class QueueRpcSupport<T> extends Foo<T> {

}

//抽象类继承普通类
abstract class Too<E> extends Boo<E> {

}

//普通类
class Zoo<E> {

}

//普通类实现接口
class Boo<E> implements Aoo<E> {
}

//普通类继承普通类
class Xoo<E> extends Zoo<E> {

}

测试结果

在这里插入图片描述

结论

  1. 接口/普通类/抽象类的组合
接口抽象类普通类
接口接口继承接口//
抽象类抽象类实现接口抽象类继承抽象类抽象类继承普通类
普通类普通类实现接口普通类继承抽象类普通类继承普通类
  1. 结果分析
    在这里插入图片描述
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值