1. 程式人生 > >Retrofit完全解析(四):Type

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

未完待續…