Gson是如何在运行时处理字段的泛型信息

来源:互联网 发布:windows boot manager 编辑:程序博客网 时间:2024/05/16 11:32

在《Gson是如何记录泛型信息的》一文中,讲述了Gson是如何通过特定的方式记录下序列化处理过程中的泛型信息。那么,在序列化的过程中,又是如何进行泛型信息的处理的?比如在处理Map类型中,该如何找到key和value的实际类型。

class Map<K, V> {    K key;    V value;}

在《Gson是如何记录泛型信息的》一文的基础上,我们已经获得到rawType以及type。
思考反序列化的过程,我们需要处理反序列化目标类型中的每一个字段。假设遇到某一字段Field,此时Gson通过$Gson$Types的resolve()函数进行处理。resolve()函数处理字段类型中的泛型信息,将其转化为实际类型。

   // 反序列过程中的执行语句   Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType());   // resolve函数   public static Type resolve(Type context, Class<?> contextRawType, Type toResolve) {    while (true) {      if (toResolve instanceof TypeVariable) {        TypeVariable<?> typeVariable = (TypeVariable<?>) toResolve;        toResolve = resolveTypeVariable(context, contextRawType, typeVariable);        if (toResolve == typeVariable) {          return toResolve;        }      } else if (toResolve instanceof Class && ((Class<?>) toResolve).isArray()) {        Class<?> original = (Class<?>) toResolve;        Type componentType = original.getComponentType();        Type newComponentType = resolve(context, contextRawType, componentType);        return componentType == newComponentType            ? original            : arrayOf(newComponentType);      } else if (toResolve instanceof GenericArrayType) {        GenericArrayType original = (GenericArrayType) toResolve;        Type componentType = original.getGenericComponentType();        Type newComponentType = resolve(context, contextRawType, componentType);        return componentType == newComponentType            ? original            : arrayOf(newComponentType);      } else if (toResolve instanceof ParameterizedType) {        ParameterizedType original = (ParameterizedType) toResolve;        Type ownerType = original.getOwnerType();        Type newOwnerType = resolve(context, contextRawType, ownerType);        boolean changed = newOwnerType != ownerType;        Type[] args = original.getActualTypeArguments();        for (int t = 0, length = args.length; t < length; t++) {          Type resolvedTypeArgument = resolve(context, contextRawType, args[t]);          if (resolvedTypeArgument != args[t]) {            if (!changed) {              args = args.clone();              changed = true;            }            args[t] = resolvedTypeArgument;          }        }        return changed            ? newParameterizedTypeWithOwner(newOwnerType, original.getRawType(), args)            : original;      } else if (toResolve instanceof WildcardType) {        WildcardType original = (WildcardType) toResolve;        Type[] originalLowerBound = original.getLowerBounds();        Type[] originalUpperBound = original.getUpperBounds();        if (originalLowerBound.length == 1) {          Type lowerBound = resolve(context, contextRawType, originalLowerBound[0]);          if (lowerBound != originalLowerBound[0]) {            return supertypeOf(lowerBound);          }        } else if (originalUpperBound.length == 1) {          Type upperBound = resolve(context, contextRawType, originalUpperBound[0]);          if (upperBound != originalUpperBound[0]) {            return subtypeOf(upperBound);          }        }        return original;      } else {        return toResolve;      }    }  }

在上述代码中,单独一行是反序列化过程中对字段类型的处理语句。其中field.getGenericType返回字段的泛型类型。在resolve()函数,则枚举进行处理字段的各种可能类型。以下类中的各字段代表resolve()中处理的各种类型。

public class Result<T> {    // TypeVariable类型,需要找到T的实际类型    T succ;    // 数组类型    Integer[] integers;    // GenericArrayType类型    T[] ts;    // ParameterizedType类型    List<T> list;    ...}

接着拆开阐述resolve中各种类型的处理过程。
1.TypeVariable类型的处理

      if (toResolve instanceof TypeVariable) {        TypeVariable<?> typeVariable = (TypeVariable<?>) toResolve;        // 处理过程        toResolve = resolveTypeVariable(context, contextRawType, typeVariable);        if (toResolve == typeVariable) {          return toResolve;        }      } 

在TypeVariable类型的处理过程中,resolveTypeVariable()函数封装了整个处理,用来找到TypeVariable变量的实际类型。

  static Type resolveTypeVariable(Type context, Class<?> contextRawType, TypeVariable<?> unknown) {    // 找到泛型变量声明的类型    Class<?> declaredByRaw = declaringClassOf(unknown);    // we can't reduce this further    if (declaredByRaw == null) {      return unknown;    }    // 获得带有泛型实际类型的类    Type declaredBy = getGenericSupertype(context, contextRawType, declaredByRaw);    if (declaredBy instanceof ParameterizedType) {      // 查询泛型变量在declaredByRaw中声明的位置      int index = indexOf(declaredByRaw.getTypeParameters(), unknown);      // 根据泛型变量声明的位置返回实际类型      return ((ParameterizedType) declaredBy).getActualTypeArguments()[index];    }    return unknown;  }  /**   * 查找泛型变量在哪个类进行声明的   */  private static Class<?> declaringClassOf(TypeVariable<?> typeVariable) {    GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration();    return genericDeclaration instanceof Class        ? (Class<?>) genericDeclaration        : null;  }   /**   * 返回带有泛型实际类型信息的类型   */  static Type getGenericSupertype(Type context, Class<?> rawType, Class<?> toResolve) {    if (toResolve == rawType) {      return context;    }    // we skip searching through interfaces if unknown is an interface    // 在resolveTypeVariable调用该函数之前,如果toResolve是接口,在直接返回了    if (toResolve.isInterface()) {      Class<?>[] interfaces = rawType.getInterfaces();      for (int i = 0, length = interfaces.length; i < length; i++) {        if (interfaces[i] == toResolve) {          return rawType.getGenericInterfaces()[i];        } else if (toResolve.isAssignableFrom(interfaces[i])) {          return getGenericSupertype(rawType.getGenericInterfaces()[i], interfaces[i], toResolve);        }      }    }    // check our supertypes    if (!rawType.isInterface()) {      while (rawType != Object.class) {        Class<?> rawSupertype = rawType.getSuperclass();        if (rawSupertype == toResolve) {          return rawType.getGenericSuperclass();        } else if (toResolve.isAssignableFrom(rawSupertype)) {          return getGenericSupertype(rawType.getGenericSuperclass(), rawSupertype, toResolve);        }        rawType = rawSupertype;      }    }    // we can't resolve this further    return toResolve;  }

从上面可以看到,resolveTypeVariable()处理泛型信息的步骤如下:
1. 获得字段声明的类(因为字段有可能是在父类或父接口中声明的)
2. 通过getSuperClass()和getGenericSuperclass()查找带有泛型实参的类
3. 获得泛型形参在类中声明的索引
4. 通过该索引在带有泛型实参的类中找到泛型的实际参数类型

2.数组类型的处理
resolve()函数对数组的处理关键是找到数组参数的实际类型。

if (toResolve instanceof Class && ((Class<?>) toResolve).isArray()) {        Class<?> original = (Class<?>) toResolve;        Type componentType = original.getComponentType();        // 获得数组元素的实际类型        Type newComponentType = resolve(context, contextRawType, componentType);        // 返回        return componentType == newComponentType            ? original            : arrayOf(newComponentType);      }

3.GenericArrayType类型的处理
可以看到,对于泛型数组的处理的关键同样是找到泛型数组元素的实际类型。

if (toResolve instanceof GenericArrayType) {        GenericArrayType original = (GenericArrayType) toResolve;        Type componentType = original.getGenericComponentType();         // 获得数组元素的实际类型        Type newComponentType = resolve(context, contextRawType, componentType);        return componentType == newComponentType            ? original            : arrayOf(newComponentType);}

4.ParameterizedType类型的处理
在ParameterizedType类型处理中,有两个泛型信息需要处理,分别是ownerType和泛型参数,同样通过递归调用resolve()方法解决。

if (toResolve instanceof ParameterizedType) {        ParameterizedType original = (ParameterizedType) toResolve;        Type ownerType = original.getOwnerType();        // 处理ownerType的泛型        Type newOwnerType = resolve(context, contextRawType, ownerType);        boolean changed = newOwnerType != ownerType;        Type[] args = original.getActualTypeArguments();        for (int t = 0, length = args.length; t < length; t++) {          // 处理ParameterizedType中的泛型类型          Type resolvedTypeArgument = resolve(context, contextRawType, args[t]);          if (resolvedTypeArgument != args[t]) {            if (!changed) {              args = args.clone();              changed = true;            }            args[t] = resolvedTypeArgument;          }        }        // 返回类型转化之后的对象        return changed            ? newParameterizedTypeWithOwner(newOwnerType, original.getRawType(), args)            : original;      }

5.WildcardType类型的处理
对于通配符类型,需要处理是通配符的上界和下界,处理方法采用递归调用resolve(),此处不再详细展开。

总结:
在Gson进行序列化/反序列的过程中,如何正确地找到字段定义的泛型参数类型是比较重要的一个步骤。不管是ParameterizedType、还是GenericArrayType类型,其最终需要处理的都是TypeVariable类型。在完成TypeVariable解析之后,都可以通过递归的方法解析出其他几种字段类型。TypeVariable类型解析的主要步骤如下:
1. 获得字段声明的类(因为字段有可能是在父类或父接口中声明的)
2. 通过getSuperClass()和getGenericSuperclass()查找带有泛型实参的类
3. 获得泛型形参在类中声明的索引
4. 通过该索引在带有泛型实参的类中找到泛型的实际参数类型

0 0
原创粉丝点击