Retrofit完全解析(四):Type<应用>

终于可以开启Retrofit > Type之旅了

从Utils类开始

getRawType

    /**
     * 获取对象的Type类型所对应的最接近的Class类型
     *      1.Type分为Class类型跟四大Type类型
     *      2.四大Type类型所对应的Class类型何解?
     *          2.1 ParameterizedType :
     *                  List<String> strList 通过 getRawType 获取List Type,再转Class
     *          2.2 GenericArrayType  :
     *                  List<String>[] strListArray > getGenericComponentType > java.util.List<java.lang.String> 为 ParameterizedType 递归2.1
     *                  最后Array.newInstance(上一步得到的Class).getClass();(创建此类型的数组对象,再获取其Class)
     *          2.3 TypeVariable :
     *                  T extends List & Serializable,因为有多个边界,所以有一个原生类型比拥有一个必要类型更ok,直接返回Object.class
     *          2.4 WildcardType :
     *                  ? extends Number ,因为现阶段通配符只接受一个上边界或下边界,所以可以获取边界后再递归getRawType,一般获取边界后直接为Class类型
     * 
     */
    static Class<?> getRawType(Type type) {
        if (type == null) throw new NullPointerException("type == null");

        if (type instanceof Class<?>) {
          // Type is a normal class.
          return (Class<?>) type;
        }
        if (type instanceof ParameterizedType) {// example: List<String>、List<T>
          ParameterizedType parameterizedType = (ParameterizedType) type;

          // I'm not exactly sure why getRawType() returns Type instead of Class. Neal isn't either but
          // suspects some pathological case related to nested classes exists.
          Type rawType = parameterizedType.getRawType();// example:List<String> 这里指 List,必定为Class
          if (!(rawType instanceof Class)) throw new IllegalArgumentException();
          return (Class<?>) rawType;
        }
        if (type instanceof GenericArrayType) {// example: Class<T>[]、Class<?>[]
          // List<String>[] pTypeArr > getGenericComponentType > java.util.List<java.lang.String> 为 ParameterizedType
          // T[] vTypeArr > getGenericComponentType > TTypeVariable
          Type componentType = ((GenericArrayType) type).getGenericComponentType();// TypeVariable  ParameterizedType
          // 返回的还是数组类型的类,数组类型的类
          return Array.newInstance(getRawType(componentType), 0).getClass();// 先找到数组的类型的class,再通过Array.newInstance去创建此类型的数组对象,再getClass
        }
        if (type instanceof TypeVariable) {// example: TT extends Number
          // We could use the variable's bounds, but that won't work if there are multiple. Having a raw
          // type that's more general than necessary is okay.
          // 我们可以是用变量的上边界,但是如果有多个,有一个原生类型比拥有一个必要类型更ok
          return Object.class;
        }
        if (type instanceof WildcardType) {// example: ?、? extends Number 、 ? super IntegerClass[]、String
          // 获取上边界,再查看上边界的原生类型
          // 现阶段通配符只接受一个上边界或下边界, 返回数组是为了以后的扩展, 实际上现在返回的数组的大小是1
          return getRawType(((WildcardType) type).getUpperBounds()[0]);
        }

        throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "
              + "GenericArrayType, but <" + type + "> is of type " + type.getClass().getName());
      }

可以看到:
1. 一个Type对象进来,不是Class就是四大Type类型。
2. 可以通过字段的Type类型,获取代码中最接近的Class的类型。
3. ParameterizedType.getRawType为何返回的是Type而不是Class?第一:其返回的不会再是四大Type 之一,必定为Class类型;第二:返回Type而不是Class的原因我觉得应该是为了各方法类型返回的统一;第三:有可能像JakeWharton所说的,猜测可能是类的嵌套会导致一些病理情况;
4. 可以猜测此方法用来获取泛型类型的具体类型,以便对象创建;我们只能通过这种方式在运行期创建最适合的对象,但是代码期并不能清楚实际创建的类型,我们仅仅只能在一个类中使用类型推断获取返回类型,并不太能跨类进行具体类型的代码层传递。

getGenericSupertype

/**
 * Returns the generic supertype for {@code supertype}. For example, given a
 * class {@code IntegerSet}, the result for when supertype is
 * {@code Set.class} is {@code Set<Integer>} and the result when the
 * supertype is {@code Collection.class} is {@code Collection<Integer>}.
 * 
 * 
 * 返回通用超类型。 例如,给定一个类IntegerSet,当超类型为Set.class时的结果为Set <Integer>,
 * 当超类型为 Collection.class 时的结果为Collection <Integer>}。
 */
static Type getGenericSupertype(Type context, Class<?> rawType,
        Class<?> toResolve) {
    if (toResolve == rawType)
        return context;

    // We skip searching through interfaces if unknown is an interface.
    // 如果toResolve是接口(如果不是接口则跳过搜索)
    if (toResolve.isInterface()) {
        // 判断rawType的接口之一会不会是toResolve
        Class<?>[] interfaces = rawType.getInterfaces();
        for (int i = 0, length = interfaces.length; i < length; i++) {
            if (interfaces[i] == toResolve) {// toResolve是rawType的接口之一
                return rawType.getGenericInterfaces()[i];// 逻辑上返回的是toResolve
            } else if (toResolve.isAssignableFrom(interfaces[i])) {// toResolve是rawType接口的父接口
                return getGenericSupertype(
                        rawType.getGenericInterfaces()[i], interfaces[i],
                        toResolve);// 通过rawType父接口类型,父接口,toResolve   继续获取父接口的通用超类(toResolve类型一致的超类)
            }
        }
    }

    // Check our supertypes. 检查超类
    // 既然toResolve不是rawType的接口,那么会不会是父类之一呢
    if (!rawType.isInterface()) {// 如果rawType也不是接口,也就是两个都是普通类
        while (rawType != Object.class) {
            Class<?> rawSupertype = rawType.getSuperclass();// 直接父类
            if (rawSupertype == toResolve) {// 父类正好为toResolve类型
                return rawType.getGenericSuperclass();// 获取父类Type
            } else if (toResolve.isAssignableFrom(rawSupertype)) {// toResolve是rawSupertype的父类
                // 递归获取父类
                return getGenericSupertype(rawType.getGenericSuperclass(),
                        rawSupertype, toResolve);// 通过父类型,父类,toResolve 继续获取父类的通用超类(toResolve类型一致的超类)
            }
            rawType = rawSupertype;
        }
    }
    // We can't resolve this further.
    // 我们不能进一步解决这个类型获取问题
    // toResolve 不是 rawType的父类或者父类的父类,也不是rawType接口 或者 父接口的接口(这里我们只能强行使用toResolve)
    return toResolve;
}

未完待续…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值