Java 获取到泛型类型

当我们需要将 Json 字符串反序列化为对象时,往往会需要使用到泛型

场景

假设我们定义了一个类,内部有一个数据结构,泛型为 T,当我们输入一个 Json 字符串,想把这个 Json 反序列化成对象,那么此时,我们就需要知道这个泛型的类型。

抽象父类:

abstract class Base<T extends Comparable<T>> {
   T data;
   public Base(String json){
      this.data = JsonUtil.toObject(json,deSerializable());
   }
}


我们想在该类中输入 Json,并将字符串反序列化成对象。比如下面这样:

/**
 * 子类定义了父类
 */
class Son extends Base<DataClass> {

  public Son(String json) {
    super(json);
  }
}

/**
 * 数据类型继承Comparable
 */
class DataClass implements Comparable<DataClass> {

  @Override
  public int compareTo(DataClass o) {
    return 0;
  }
}

子类定义了泛型,但是泛型类型的获取是在父类中,所以重点在 deSerializale()方法的实现上,我们需要一个 Class<T> 能够让 Json 工具正常序列化。

如何实现?

通过 Java 反射包的 ParameterizedType 工具获得泛型具体类型。

public static void main(String[] args) {
    String json = JsonUtil.toJson(new DataClass());
    Son s = new Son(json);
    Type t = s.getClass().getGenericSuperclass();
    if (t instanceof ParameterizedType) {
      System.out.println(t);
      // output: cn.think.in.java.clazz.loader.generics.Base<cn.think.in.java.clazz.loader.generics.DataClass>
      for (Type type : ((ParameterizedType) t).getActualTypeArguments()) {
        System.out.println(type);
        //output: class cn.think.in.java.clazz.loader.generics.DataClass
      }
    }
  }

首先我们将一个对象序列化成 Json 字符串,模拟外部输入。然后呢?创建一个子类对象,得到这个 Son 的 Class 。
关键地方来了,调用 getGenericSuperclass 方法,这个方法的作用是:返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type

所以这里会得到一个 ParameterizedTypeImpl 类型的对象。注意:这个类是 Sun 包下的,不是开源的。该类有以下几个属性:

Java返回一个泛型 java 返回泛型类型_json


actualTypeArguments:获取到父类的泛型数组;

rawType:原始类型,即 Base 的Class类型;

OwnerType:返回的是 Base 类型;

那么可以定义 deSerilizable() 方法如下:

private Class<T> deSerializable() {
    Type type = getClass().getGenericSuperclass();
    if (type instanceof ParameterizedType) {
      ParameterizedType parameterizedType = (ParameterizedType) type;
      System.out.println(parameterizedType.getActualTypeArguments()[0]);
      return (Class<T>) parameterizedType.getActualTypeArguments()[0];
    }
    throw new RuntimeException();
  }

这样就得到了父类中的泛型类型的 Class对象,能够采用 Json 序列化的方法。