guava 泛型
Java 5之前 Java的设计者没有考虑范型引入jvm,后果是 Java 已经发展了很多年,形成历史技术债务。
2022/5/25 10:25:37
➡️

范型的历史机源

Java 5之前 Java的设计者没有考虑范型引入jvm,后果是 Java 已经发展了很多年,形成历史技术债务。

Java 语言以及 JVM 推出后,由于它的跨平台性,通用的字节码,虚拟机,它能够运行在 Web 上,GC 等特性,迅速在全球流行开来,同时也吸引了很多学界和产业界人士的关注,其中就包括当时在德国卡尔斯鲁厄大学任教的 Martin Odersky(也是 scala 之父)。他和其在英国格拉斯哥大学的研究伙伴 Phil Wadler 于 1996 年共同开发了 Pizza 语言,该语言运行在 JVM 上,支持泛型,高阶函数和模式匹配等函数式编程功能。由于 Pizza 的目标是填补 Java 欠缺的功能,因此受到 Sun 公司的关注,于是 Sun 的工程师和 Martin Odersky、Phil Wadler 合作,借鉴 Pizza 的泛型实现开发了支持泛型的 Java 扩展版本:GJ,即 Generic Java。

GJ 所支持的泛型支持同类转化(homogeneous,指编译器把泛型中的类型参数都翻译为相同的 Object),异类转化(heterogeneous,指编译器把不同类型参数的泛型翻译为不同参数化的类),支持值类型范型。但由于要兼容不支持泛型的旧版本,Java 最终采用了类型擦除(type erasure)这一同类转化的方案,并引入了通配符,这样就构成了 2004 年发布的 Java 5 的泛型的基础

Java 的泛型仍在进化,JEP218 即 Project Valhalla 旨在支持值类型范型,并引入泛型可 reifiable 机制,即在运行时可读取类型参数的类型信息,但发布时间尚未确定。

泛型的设计理念

通过类型擦除实现 Java 泛型。为了兼容旧版本,Java 的设计者认为对于 JVM 来讲不支持泛型的代码应当和支持泛型的代码是透明的,两者没有区别;同时也不想为泛型开发一套新的平行的 API,最终采用了类型擦除的方案。所有的泛型类型参数都在编译期间转为 Object 对象,而基本类型 int、long、double 等不是对象类型,所以 Java 泛型暂不支持基本类型。

保证类型安全,避免运行时 ClassCastException。泛型有助于在编译期检查代码的类型安全,采用范型的代码要能够保证运行期不会出现 ClassCastException。保证类型安全这一点对于 OOP 语言至关重要,它通过编译期严格的类型检查,有效避免运行时的错误。

//无论范型是什么类型,编译后会进行类型擦除,变成 object
List<Object> list=new ArrayList<Object>();

/*
* 编译器强制要求表达式俩边是统一的类型,目的是保证不发生 ClassCastException 异常
* 如果编译器支持以下的代码,第一行代码会引入 ClassCastException 异常 
* 第二行代码会进行强制转换,没有必要
* 第二行的代码也没有继承关系,不能说 String 继承 Object 就是集合也存在继承关系
* 因为 new ArrayList<String> 其实是 ArrayList<Object>()
*/
❌ List<String> strList=new ArrayList<Object>();
❌ List<Object> objList=new ArrayList<String>();

验证类型擦除,在 jvm 里 输出一样的结果,说明引入范型号只是编译器层面方便程序员写出规范代码 到jvm 里都是 Object,保证了 java5 之前的代码,能够继续使用,在 jvm 里根本没有范型这个概念

var bar= new ArrayList<String>().getClass();
var foo= new ArrayList<Integer>().getClass();
var zar= new ArrayList<Object>().getClass();
var zoo= new ArrayList().getClass();
System.out.println(bar.getName()); //java.util.ArrayList
System.out.println(foo.getName()); //java.util.ArrayList
System.out.println(zar.getName()); //java.util.ArrayList
System.out.println(zoo.getName()); //java.util.ArrayList

❌异常类不能被泛化,如下代码是不允许的,因为这样没有意义

class  MyException<T> extends Exception{
}

try {}catch (MyException<String> e){}
      catch (MyException<Integer> e){}
//编译后变成这样,那到底是进入第一个 catch 还是第二个 catch 合适 
//会引起混乱,所以编译器不允许 异常类泛化
try {}catch (MyException<Object> e){}
      catch (MyException<Object> e){}

✅ 但可以声明类型变量为异常类

class  ThrowException<E extends  Exception>{
    void  errMethod(E e) throws Exception {throw  e;}
}


❌方法重载不成立,类型擦除后都是 ArrayList<Object>
//'method(ArrayList<String>)' 与 'method(ArrayList<Date>)' 冲突;两个方法具有相同的擦除
public class Test {
public  void method(ArrayList<String> list) {
    System.out.println("Arraylist<String> list");
  }

public  void method(ArrayList<Date> list) {
    System.out.println("Arraylist<Date> list");
  }
}

基本的使用

一般普遍常用的泛型名字:

  • E - Element 容器类元素
  • K — Key map 中的 key
  • N - Number
  • T - Type
  • V - Value
  • S,U,V etc. - 2nd, 3rd, 4th types

泛型不适合父子继承关系,会破环继承关系

public class A {
  @Data
 public static class Parent<T> { private  T t;}
  
 public static class Child extends  Parent<Date>{
   @Override
   public Date getT() {return super.getT();}
   @Override
   public void setT(Date date) {super.setT(date);}
 }

 public static  void main(String[] args)  {
    //子类的泛型参数是 Date
    Child child=new Child();
    child.setT(new Date());
    var bar= child.getT();
    
    //这里的父类,泛型参数是 Object ,因为默认不指定就是 object 
    Parent parent=child;
    //虽然父类指向了子类,泛型破环了父子类的继承关系,此时在编译器看来setT() 是用的父类的方法约束,
    //但是jvm 哪里执行的却是子类的方法
    //运行时❌抛出错误 class java.lang.String cannot be cast to class java.util.Date
    //此错误在编译器不会发现
    parent.setT("");
    var foo=parent.getT();
 }
}

自定义比较大小

public class Bar {
  public static  <T extends Comparable<T>> T max(T t1,T t2){
        return (t1.compareTo(t2)>0) ?t1:t2;
  }
  public static void main(String[] args) {
    System.out.println(max(10,5));
  }
}

范型的桥接方法

继承关系的泛型类

public abstract class Parent<T> {
  abstract T get(T t);
}

//
public class Sun extends Parent<String> {
  @Override
  String get(String s) {
    return "";
  }
}

如果编译后是这样的代码,继承关系就破环了,语法上就通不过

public abstract class Parent {
  abstract Object get(Object t);
}

//
public class Sun extends Parent<String> {
  @Override
  String get(String s) {
    return "";
  }
}

利用编译器桥接生成的代码可以保留继承关系,同时有能保留原来的方法 get(String s)

//类型擦除
public abstract class Parent {
  abstract Object get(Object t);
}

public class Sun extends Parent<String> {
  /*
  Parent 类型会被擦除为 Object
  需要保留原来的 Parent 的原来的方法
  👍👍👍编译器添加的桥接方法  
  */
  public Object get(Object t){
     return  get((String) t);
  }

  //但是这里的方法参数还要保留到运行时
  @Override
  public String get(String s) {
    return s;
  }
}

泛型的上下边界和通配符

上下边界 extends

通过 extends 限制泛型参数边界,如下显示,不能有多继承类,但是允许有多个接口,继承的类必须位于开头位置

<T extends B1 & B2 & B3>
class Order{ }

interface Cargo{ }

class  Far  extends  Order implements Cargo,Serializable{
}

public class A {
 //通过 extends 限制泛型参数只能是  Order & 实现 Cargo & Serializable 的类或其子类
 public  static <T extends Order & Cargo & Serializable> T getFirst(List<T> list){
     var ret =list.get(0);
     return ret;
 }

 public static  void main(String[] args)  {
   var list =new ArrayList<Far>();
   getFirst(list);
 }
}

通配符 ——协变(Covariance)和逆变(Contravariance)

泛型是与 OOP 强关联的技术,而协变和逆变也是关于继承关系的理论,因此两者在很多方面是贯通的。 里氏替换原则,它指出如果一个类型 S 是类型 T 的子类,那么程序中任何 T 的对象出现的地方都可以用 S 的对象来替换,因为 S 的对象包含了 T 的对象的所有信息。这里的类型不一定就是类,也可以是接口、函数或方法 。里氏替换原则是协变和逆变的基础

首先,协变和逆变这两个概念在数学和物理界已经应用很广泛,它强调的是当变量发生变化时,所研究对象变化的方向与该变量变化的方向是否一致,如果一致就是协变,否则就是逆变。 y=f(x) 如果 x 变大 y 也变大,就是协变,否者就是逆变,就是这么简单

Java泛型中的通配符机制的目的是:让一个持有特定类型(比如A类型)的集合能够强制转换为持有A的子类或父类型的集合,通配符是配合泛型集合使用的

泛型通配符可以解决这个问题。泛型通配符主要针对以下两种需求:

  • 从一个泛型集合里面读取元素 上界通配符,作为函数的参数
  • 往一个泛型集合里面插入元素 下界通配符,作为函数的返回值 这里有三种方式定义一个使用泛型通配符的集合(变量)。如下:
<?>           
<? extends A> 指定上界
<? super A>   指定下界

泛型的通配符 ?,有的时候也称为无边界通配符,就是传递啥都可以

为什么要有通配符,因为集合类型之间不存在继承关系,通过通配符来适配这种关系

✅ Object obj1="hello";
✅ Object obj2=1;

//按照 上面的例子如下例子看似可以通过编译,实际却不能通过编译
❌ArrayList<Object> strList=new ArrayList<String>();
❌ArrayList<Object> intList=new ArrayList<Integer>();

如果泛型的集合允许把子类集合赋值给父类集合

class Parent{
}
class Child1 extends Parent {
}
class Child2 extends Parent {
}

class GenericsType {
  public static void main(String[] args) {
     var list = new ArrayList<Child1>();
     list.add(new Child1());

     ❓ List<Parent> parentList=list;
     //就算上面的编译能通过
     //这里 parentList 添加 Child1 及 Parent 的后果是类型转换错误
     //因为 Child1 不能传入不是自己及其子类的类型对象
     parentList.add(new Child2());
     parentList.add(new Parent());
  }
}

如下例子printList 方法的参数是 List list,但是编译器会提示 需要的类型:List,提供的类型:List 编译不通过,集合之间不存在继承关系

class GenericsType {
  public static void main(String[] args) {
    List<String> list = new ArrayList<>(){
      {add("hello");}
    };
    List<Integer> list2 = new ArrayList<>(){
      {add(1);}
    };

    ❌ GenericsType.printList(list);
    ❌ GenericsType.printList(list2);
  }
  public static void printList(❌ List<Object> list) {
    list.forEach(p->{
      System.out.print(p + " ");
    });
  }
}

代码改成如下形式编译通过 因为你不知道集合是哪种类型,所以你只能够对集合进行读操作。并且你只能把读取到的元素当成 Object 实例来对待。 下面是一个例子:

public static void printList(✅ List<?> list) {
  //不能修改增加元素,但是可以删除元素
  list.forEach(p->{
    // p 是啥类型这里根本不知道,只能是当作 object 对待,因为不知道集合元素是什么类型
    // 不能给集合添加类型
    System.out.print(p + " ");
  });
}

? 通配符的限界

演示类

interface superParentInterface {
}

interface ParentInterface extends superParentInterface {
}

interface UncleInterface extends superParentInterface {
}


class superParent1 implements superParentInterface{
}

class Parent1  implements ParentInterface {
}

class Uncle1 implements UncleInterface {
}


class superParent {
}

class Parent extends superParent implements ParentInterface {
}

class Uncle extends superParent {
}

class Child1 extends Parent {
}

class Child2 extends Parent {
}

class Son1 extends Child1 {
}

class Son2 extends Child1 {
}

上界通配符

上界通配符,用来指定范围的上边界,不限制下边界。堵住往上的路,来缩小类型参数的类型范围,传入的类型只能是Parent(上边界) 及其子类 Child1 或 Child2,它的语法形式为:<? extends Parent>

class GenericsType {
  public static void main(String[] args) {
     {
      var list1 = new ArrayList<Child1>();
      doSome(list1);

      var list2 = new ArrayList<Child2>();
      doSome(list2);
    }
    {
      var list1 = new ArrayList<Son1>();
      doSome(list1);

      var list2 = new ArrayList<Son2>();
      doSome(list2);
    }

    {
      var list1 = new ArrayList<Parent>();
      doSome(list1);

      var list2 = new ArrayList<ParentInterface>();
      doSome(list2);

      var list3 = new ArrayList<Parent1>();
      doSome(list3);
    }

    {
      var list1 = new ArrayList<superParent>();
doSome(list1);

      var list2 = new ArrayList<superParentInterface>();
doSome(list2);

      var list3 = new ArrayList<superParent1>();
doSome(list3);
    }

    {
      var list1 = new ArrayList<Uncle>();
doSome(list1);

      var list2 = new ArrayList<Uncle1>();
doSome(list2);

      var list3 = new ArrayList<UncleInterface>();
doSome(list3);
    }

    {
      var list = new ArrayList<Object>();
doSome(list);
    }
  }
  public  static  void doSome(List<? extends ParentInterface > list) {
    //不能修改增加元素,但是可以删除元素
    //因为虽然有上界了,但是还是无法确定 list 的元素类型 是  Parent 或 Parent1 ,还是Parent的 子类 Child1 或 Child2 等子类
    ❌list.add(new Parent());
    ❌list.add(new Parent1());
    ❌list.add(new Child1());
    ❌list.add(new Child2());
    ❌list.add(new Object());
    for (Parent item: list) {
      System.out.println(item + ";");
    }
  }
}

如图中蓝色框的是上界通配符限制的范围,它限制了上界的边界,下界不限制,只要是子类就可以,子类就会有很多分叉

上界

下界通配符

下界通配符,用来指定范围的下边界堵住往下的路,但是往上的路虽然没有堵,但是进行了限制。传入的类型只能是Child1(下边界) 及其父类的父类 等 Parent ,它的语法形式为:<? super Child1>

class GenericsType {
 public static void main(String[] args) {
     {
      var list1 = new ArrayList<Child1>();
      doSome(list1);

      var list2 = new ArrayList<Child2>();
doSome(list2);
    }
    {
      var list1 = new ArrayList<Son1>();
doSome(list1);

      var list2 = new ArrayList<Son2>();
doSome(list2);
    }

    {
      var list1 = new ArrayList<Parent>();
      doSome(list1);

      var list2 = new ArrayList<ParentInterface>();
      doSome(list2);

      var list3 = new ArrayList<Parent1>();
doSome(list3);
    }

    {
      var list1 = new ArrayList<superParent>();
      doSome(list1);

      var list2 = new ArrayList<superParentInterface>();
      doSome(list2);

      var list3 = new ArrayList<superParent1>();
doSome(list3);
    }

    {
      var list1 = new ArrayList<Uncle>();
doSome(list1);

      var list2 = new ArrayList<Uncle1>();
doSome(list2);

      var list3 = new ArrayList<UncleInterface>();
doSome(list3);
    }

    {
      var list = new ArrayList<Object>();
      doSome(list);
    }
  }

  public static void doSome(List<? super Child1> list) {
    //这里可以肯定的是 list 里的元素类型不是 Parent及父类 就是 Child1 这俩种类型
    //所以插入 Child1 及其子类型是肯定安全的
    list.add(new Child1());
    list.add(new Son1());
    //因为 list 的元素类型有可能是 Child1 ,插入 Parent 会发生类型转换错误,
    //在往上插入就更不安全了
    ❌list.add(new Parent());
  }
}

如图中蓝色框的是下界通配符限制的范围,它限制了下界,上界的顶不限制,但是只能沿着父类父类方向,而且不能有分叉 下界

泛型的反射

一个类可以继承自一个泛型类。例如:父类的类型是Pair,子类的类型是IntPair,可以这么继承:

public class IntPair extends Pair<Integer> {
}

我们无法获取Pair的T类型,即给定一个变量Pair p,无法从p中获取到Integer类型。 但是,在父类是泛型类型的情况下,编译器就必须把类型T(对IntPair来说,也就是Integer类型)保存到子类的class文件中,不然编译器就不知道IntPair只能存取Integer这种类型。在继承了泛型类型的情况下,子类可以获取父类的泛型类型

因为Java引入了泛型,所以,只用Class来标识类型已经不够了。实际上,Java的类型系统结构如下:

graph TB Type -->Class Type -->ParameterizedType Type -->GenericArrayType Type -->WildcardType Type -->TypeVariable

Type直接子接口: ParameterizedType,GenericArrayType,TypeVariable和WildcardType四种类型的接口

  • ParameterizedType: 表示一种参数化的类型,比如Collection
  • GenericArrayType: 表示一种元素类型是参数化类型或者类型变量的数组类型
  • TypeVariable: 是各种类型变量的公共父接口
  • WildcardType: 代表一种通配符类型表达式,比如?, ? extends Number, ? super Integer【wildcard是一个单词:就是“通配符”】

参数化类型 ParameterizedType

/**
 *  参数化泛型
 */
public interface ParameterizedType extends Type {
    /**
     * 这个 Type 类型的参数的实际类型数组。 如 Map<String,Person> map 
       这个ParameterizedType 返回的是 String 类,Person 类的全限定类名的 Type Array。
     */
    Type[] getActualTypeArguments();
 
    /**
     * 返回的是当前这个 ParameterizedType 的类型。 如 Map<String,Person> map 
       这个ParameterizedType 返回的是 Map 类的全限定类名的 Type Array。
     */
    Type getRawType();
 
    /**
      *(可以简单理解为:外部类与内部类的关系,此操作为获取该对象(内部类)的外部类)
     */
    Type getOwnerType();
}
class GenericsTypeDemo<T1,T2> { }
class TypeDemo extends GenericsPair<Integer,String> { }

class GenericsType {
  public static void main(String[] args){
    {
      var type = TypeDemo.class.getGenericSuperclass();
      if (type instanceof ParameterizedType) {
        var pt = (ParameterizedType) type;

        System.out.println(pt.getTypeName());
        // class com.hank.genericity.Pair
        System.out.println(pt.getRawType());
        // com.hank.genericity.Pair<java.lang.Integer, java.lang.String>
       
        //获取内部类的外部持有者
        System.out.println(pt.getOwnerType());
        // null

        //获选泛型类的泛型参数
        var types = pt.getActualTypeArguments();
        Arrays.stream(types).forEach(p -> {
          System.out.println(p.getTypeName());
          //java.lang.Integer
          //java.lang.String
        });
      }
    }
  }
}

参数化范型数组类型 GenericArrayType

public interface GenericArrayType extends Type {
    //获取泛型数组的参数类型
    Type getGenericComponentType();
}

GenericArrayType 如果类内不保存泛型参数类型,这些参数化类型信息就会丢失

class GenericArrayTypeDemo<T> {
  List<String>[] pTypeArray;
  //类型名java.util.List<java.lang.String>[]
  //泛型数组参数类型java.util.List<java.lang.String>


  T[] vTypeArray;
  //类型名T[]
  //泛型数组参数类型T

  Person<String, Integer>[] persons;
  //类型名com.hank.genericity.Person<java.lang.String, java.lang.Integer>[]
 //泛型数组参数类型com.hank.genericity.Person<java.lang.String, java.lang.Integer>

  //不属于
  String[] strings;


  public void doSome(List<String>[] pTypeArray){
  //类型名java.util.List<java.lang.String>[]
  //泛型数组参数类型java.util.List<java.lang.String>
  }
}

//
class GenericsType {
  public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException {
    var fields =  GenericArrayTypeDemo.class.getDeclaredFields();
    Arrays.stream(fields).forEach(p->{
         var type = p.getGenericType();
         if(type instanceof GenericArrayType){
            var genericArrayType=(GenericArrayType) type;
            System.out.println("类型名"+genericArrayType.getTypeName());
            System.out.println("泛型数组参数类型"+genericArrayType.getGenericComponentType());
         }
    });
    List<String>[] pTypeArray=new List[0];
    var clazz =   pTypeArray.getClass();
    var methods = GenericArrayTypeDemo.class.getMethod("doSome",clazz);
    var types=methods.getGenericParameterTypes();
    Arrays.stream(types).forEach(p->{
      if(p instanceof GenericArrayType){
        var genericArrayType=(GenericArrayType) p;
        System.out.println("类型名"+genericArrayType.getTypeName());
        System.out.println("泛型数组参数类型"+genericArrayType.getGenericComponentType());
      }
    });
  }
}

参数化范型 type 类型 TypeVariable

/**
 * TypeVariable
 */
public interface TypeVariable<D extends GenericDeclaration> extends Type, AnnotatedElement {
    /**
     * 得到上边界的 Type数组,如 K 的上边界数组是 InputStream 和 Serializable。 V 没有指定的话,
     * 上边界是 Object
    */
    Type[] getBounds();
 
    /**
     * 返回的是声明这个 Type 所在的类 的 Type
     */
    D getGenericDeclaration();
 
    /**
     * 返回的是这个 type variable 的名称
     */
    String getName();
 
    /**
     * AnnotatedType表示当前在此VM中运行的程序中可能注释使用的类型。 
       该用途可以是Java编程语言中的任何类型,包括数组类型,参数化类型,类型变量或通配符类型。
     * 通过AnnotatedType的getType()方法,获得其上边界的 Type,如 K 的上边界数组是 InputStream 和 
       Serializable。
       V 没有指定的话,上边界是 Object
     */
     AnnotatedType[] getAnnotatedBounds();
}
class  Person<T> {
}

class GenericArrayTypeDemo<T extends Person<T> & Serializable,V> {
  T t;
  /**
  type variable:T
  type variable 的上边界:com.hank.genericity.Person<T>;java.io.Serializable
  Type 所在的类 的 Type:class com.hank.genericity.GenericArrayTypeDemo
  */
  V v;
  /**
  type variable:V
  type variable 的上边界:java.lang.Object  //不指定上边界就是 object
  Type 所在的类 的 Type:class com.hank.genericity.GenericArrayTypeDemo
  */

  //不属于 TypeVariable
  V[] values;
  String str;
}

class GenericsType {
  public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException {
    var fields =  GenericArrayTypeDemo.class.getDeclaredFields();
    Arrays.stream(fields).forEach(p->{
         var type = p.getGenericType();
         if(type instanceof TypeVariable){
            var typeVariable=(TypeVariable) type;

            System.out.println("type variable:"+typeVariable.getName());

            var arr= Arrays.stream(typeVariable.getBounds()).map(q->q.getTypeName()).
                             collect(Collectors.toList());
            System.out.println("type variable 的上边界:"+ String.join(";",arr));
            System.out.println("Type 所在的类 的 Type:"+typeVariable.getGenericDeclaration());
         }
    });
  }
}

通配符泛型类 WildcardType

public interface WildcardType extends Type {
  /**
    * 上边界
    */
  Type[] getUpperBounds();

  /**
    * 下边界
    */
  Type[] getLowerBounds();
}
class GenericArrayTypeDemo {
  List<? extends Number> list1;
  /**
   * 上边界:java.lang.Number
   * 下边界:
   */

  List< ? super String> list2;
  /**
   * 上边界:java.lang.Object
   * 下边界:java.lang.String
   */

  List< ? > list3;
  /**
   * 上边界:java.lang.Object
   * 下边界:
   */
}

class GenericsType {
  public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException {
    var fields =  GenericArrayTypeDemo.class.getDeclaredFields();
    Arrays.stream(fields).forEach(p->{
         //先获取参数话类型
         var type = p.getGenericType();
         
         if(type instanceof ParameterizedType){
            var parameterizedType=(ParameterizedType) type;
            var arg0= parameterizedType.getActualTypeArguments()[0];
            //在获取通配符类型
            if(arg0 instanceof WildcardType ){
              var wildcardType=(WildcardType) arg0;

              var arr= Arrays.stream(wildcardType.getUpperBounds()).
                   map(q->q.getTypeName()).collect(Collectors.toList());
              System.out.println("上边界:"+ String.join(";",arr));

              var arr1= Arrays.stream(wildcardType.getLowerBounds()).
                   map(q->q.getTypeName()).collect(Collectors.toList());
              System.out.println("下边界:"+ String.join(";",arr1));
            }
         }
    });
  }
}

Spring 对泛型反射的封装 ResolvableType

提供方便的API,如下:

  • ResolvableType.forClass
  • ResolvableType.forMethodParameter
  • ResolvableType.forMethodReturnType
  • ResolvableType.forField
  • ResolvableType.forConstructorParameter

获取父类的泛型

resolvedType.getSuperType() 获取泛型父类型

class GenericsType {
  static class Person<T, V> {}
  static class Student extends Person<String, Integer> {}

  public static void main(String[] args) throws NoSuchMethodException, ClassNotFoundException {
    //用JDK 的方式获取
    var type =Student.class.getGenericSuperclass();
    if(type instanceof ParameterizedType){
       var parameterizedType =(ParameterizedType)type;
      Arrays.stream(parameterizedType.getActualTypeArguments()).forEach(p->{
         var name =   p.getTypeName();
          System.out.println(name);
         /**
         * java.lang.String
         * java.lang.Integer
         */
      });
    }
    
    // ResolvableType 的 API   getSuperType 实现
    var resolvedType =  ResolvableType.forClass(Student.class);
    Arrays.stream(resolvedType.getSuperType().getGenerics()).forEach(p->{
        var aClass=p.resolve();
        System.out.println(aClass.getName());
        /**
         * java.lang.String
         * java.lang.Integer
         */
    });
  }
}

获取接口上的泛型

resolvedType.getInterfaces() 实现获取泛型接口

class GenericsType {
  static interface Person<T, V> {}
  static class Student implements Person<String, Integer> {}

  public static void main(String[] args){
    //用JDK 的方式获取
    var type =Student.class.getGenericInterfaces();
    if(type[0] instanceof ParameterizedType){
       var parameterizedType =(ParameterizedType)type[0];
      Arrays.stream(parameterizedType.getActualTypeArguments()).forEach(p->{
         var name =   p.getTypeName();
          System.out.println(name);
         /**
         * java.lang.String
         * java.lang.Integer
         */
      });
    }
  
    // ResolvableType 的 API   getInterfaces 实现
    var resolvedType =  ResolvableType.forClass(Student.class);
    Arrays.stream(resolvedType.getInterfaces()[0].getGenerics()).forEach(p->{
        var aClass=p.resolve();
        System.out.println(aClass.getName());
        /**
         * java.lang.String
         * java.lang.Integer
         */
    });
  }
}

获取属性上的泛型

class GenericsType {
  private  List<String> listString;
  private  List<List<String>> listLists;
  private  Map<String, Long> maps;
  
  public static void main(String[] args)  {
    //用JDK 的方式获取
    Arrays.stream(GenericsType.class.getDeclaredFields()).forEach(p->{
       var  type =   p.getGenericType();
       if(type instanceof ParameterizedType){
           var parameterizedType = (ParameterizedType) type;
           Arrays.stream(parameterizedType.getActualTypeArguments()).forEach(q->{

             //嵌套的要自己处理
             if(q instanceof ParameterizedType){
                var parameterizedType1 =(ParameterizedType) q;
                 Arrays.stream(parameterizedType1.getActualTypeArguments()).forEach(l->{
                 System.out.println(l.getTypeName());
               });

             }else {
               System.out.println(q.getTypeName());
             }
         });
       }
    });
    /**
     * java.lang.String
     * java.lang.String
     * java.lang.String
     * java.lang.Long      
     */

    // ResolvableType 的 API  ResolvableType.forField
    Arrays.stream(GenericsType.class.getDeclaredFields()).forEach(p->{
      var resolvedType =
          ResolvableType.forField(ReflectionUtils.findField(GenericsType.class,p.getName()));
      Arrays.stream(resolvedType.getGenerics()).forEach(q->{
          
          //嵌套的要自己处理
          if(q.getGenerics().length>0){
            Arrays.stream(q.getGenerics()).forEach(l->{
                var aClass=l.resolve();
                System.out.println(aClass.getTypeName());
            });
          }else{
            var aClass=q.resolve();
            System.out.println(aClass.getTypeName());
          }
      });
    });
    /**
     * java.lang.String
     * java.lang.String
     * java.lang.String
     * java.lang.Long      
     */
  }
}

获取属性上的通配符泛型边界

class GenericsType {
  private List<? extends Number> list;

  public static void main(String[] args) {
    //用JDK 的方式获取
    Arrays.stream(GenericsType.class.getDeclaredFields()).forEach(p -> {
      var type = p.getGenericType();
      if (type instanceof ParameterizedType) {
        var parameterizedType = (ParameterizedType) type;
        Arrays.stream(parameterizedType.getActualTypeArguments()).forEach(q -> {
          //嵌套的要自己处理
          if (q instanceof WildcardType) {
            var wildcardType = (WildcardType) q;

            System.out.println(wildcardType.getTypeName());
            var arr = Arrays.stream(wildcardType.getUpperBounds()).map(n -> n.getTypeName()).
                collect(Collectors.toList());
            System.out.println("上边界:" + String.join(";", arr));

            var arr1 = Arrays.stream(wildcardType.getLowerBounds()).map(n -> n.getTypeName()).
                collect(Collectors.toList());
            System.out.println("下边界:" + String.join(";", arr1));

          } else {
            System.out.println(q.getTypeName());
          }
        });
      }
    });
    /**
     * ? extends java.lang.Number
     * 上边界:java.lang.Number
     * 下边界:
     */

    // ResolvableType 的 API  ResolvableType.forField
    Arrays.stream(GenericsType.class.getDeclaredFields()).forEach(p -> {
      var resolvedType =
          ResolvableType.forField(ReflectionUtils.findField(GenericsType.class, p.getName()));
      Arrays.stream(resolvedType.getGenerics()).forEach(q -> {
        var type = q.getType();
        if (type instanceof WildcardType) {
          var wildcardType = (WildcardType) type;

          System.out.println(wildcardType.getTypeName());
          var arr = Arrays.stream(wildcardType.getUpperBounds()).map(n -> n.getTypeName()).
                                  collect(Collectors.toList());
          System.out.println("上边界:" + String.join(";", arr));

          var arr1 = Arrays.stream(wildcardType.getLowerBounds()).map(n -> n.getTypeName()).
                                  collect(Collectors.toList());
          System.out.println("下边界:" + String.join(";", arr1));

        } else {
          System.out.println(type.getTypeName());
        }
      });
    });
    /**
     * ? extends java.lang.Number
     * 上边界:java.lang.Number
     * 下边界:
     */
  }
}
👍🎉🎊