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;
}

未完待續…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章