GSON源碼解析

Gson源碼解析

Gson的解析原理大致分爲如下兩種情況。
1.如果是通過GsonBuilder創建的Gson對象,那麼就用自定義的TyperAdapter來完成json的解析
2.如果是通過new Gson()創建的Gson對象,那麼就用Java反射機制來完成json的解析。
那麼Gson在是怎麼判斷是上述兩種方式的哪一種呢?我們查看源碼時,並沒有提供一個特殊的字段來辨別?

Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy,
    final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
    boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
    boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
    LongSerializationPolicy longSerializationPolicy,
    List<TypeAdapterFactory> typeAdapterFactories) {
 

  List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();

  // built-in type adapters that cannot be overridden
  factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);
  factories.add(ObjectTypeAdapter.FACTORY);

  // the excluder must precede all adapters that handle user-defined types
  factories.add(excluder);

  // user's type adapters
  factories.addAll(typeAdapterFactories);

  // type adapters for basic platform types
  factories.add(TypeAdapters.STRING_FACTORY);
  factories.add(TypeAdapters.INTEGER_FACTORY);
  factories.add(TypeAdapters.BOOLEAN_FACTORY);
  factories.add(TypeAdapters.BYTE_FACTORY);
  factories.add(TypeAdapters.SHORT_FACTORY);
  TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy);
  factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));
  factories.add(TypeAdapters.newFactory(double.class, Double.class,
          doubleAdapter(serializeSpecialFloatingPointValues)));
  factories.add(TypeAdapters.newFactory(float.class, Float.class,
          floatAdapter(serializeSpecialFloatingPointValues)));
  factories.add(TypeAdapters.NUMBER_FACTORY);
  factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY);
  factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);
  factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));
  factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));
  factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY);
  factories.add(TypeAdapters.CHARACTER_FACTORY);
  factories.add(TypeAdapters.STRING_BUILDER_FACTORY);
  factories.add(TypeAdapters.STRING_BUFFER_FACTORY);
  factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));
  factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));
  factories.add(TypeAdapters.URL_FACTORY);
  factories.add(TypeAdapters.URI_FACTORY);
  factories.add(TypeAdapters.UUID_FACTORY);
  factories.add(TypeAdapters.CURRENCY_FACTORY);
  factories.add(TypeAdapters.LOCALE_FACTORY);
  factories.add(TypeAdapters.INET_ADDRESS_FACTORY);
  factories.add(TypeAdapters.BIT_SET_FACTORY);
  factories.add(DateTypeAdapter.FACTORY);
  factories.add(TypeAdapters.CALENDAR_FACTORY);
  factories.add(TimeTypeAdapter.FACTORY);
  factories.add(SqlDateTypeAdapter.FACTORY);
  factories.add(TypeAdapters.TIMESTAMP_FACTORY);
  factories.add(ArrayTypeAdapter.FACTORY);
  factories.add(TypeAdapters.CLASS_FACTORY);

  // type adapters for composite and user-defined types
  factories.add(new CollectionTypeAdapterFactory(constructorConstructor));
  factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));
  this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);
  factories.add(jsonAdapterFactory);
  factories.add(TypeAdapters.ENUM_FACTORY);
  factories.add(new ReflectiveTypeAdapterFactory(
      constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));

  this.factories = Collections.unmodifiableList(factories);
}

從上述源碼可知,通過Gson的factories(List) 這個對象add TypeAdapterFactory的順序來控制的!當是用第一種方式來創建Gson對象的時候,把自定一個TypeAdapter或者TypeAdapterFactory添加在factories靠前的位置,然後在getAdapter方法中遍歷factories的每一個TypeAdapterFactory,如果當前循環中的TypeAdapterFactory.create 返回的TypeAdapter!=null,就返回該Adapter退出了factories的遍歷.因爲自定義的TypeAdapter位置在factories中靠前這樣就優先與ReflectiveTypeAdapterFactory 遍歷到,所以就避免了用Gson的反射機制來解析json了。

fromJson的一般調用方法

public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
  Object object = fromJson(json, (Type) classOfT);
  return Primitives.wrap(classOfT).cast(object); //這裏控制返回類型與傳入的Class類型一致
}


  /**
   * Returns the corresponding wrapper type of {@code type} if it is a primitive
   * type; otherwise returns {@code type} itself. Idempotent.
   * <pre>
   *     wrap(int.class) == Integer.class
   *     wrap(Integer.class) == Integer.class
   *     wrap(String.class) == String.class
   * </pre>
   */
  public static <T> Class<T> wrap(Class<T> type) {
    // cast is safe: long.class and Long.class are both of type Class<Long>
    @SuppressWarnings("unchecked")
    Class<T> wrapped = (Class<T>) PRIMITIVE_TO_WRAPPER_TYPE.get(
        $Gson$Preconditions.checkNotNull(type));
    return (wrapped == null) ? type : wrapped;
  }

  public T cast(Object obj) {
        if (obj != null && !isInstance(obj))
            throw new ClassCastException(cannotCastMsg(obj));
        return (T) obj;
    }

根據註釋可以瞭解,Primitives的這個方法會根據傳入的類型進行判斷,對基本類型的參數進行包裝,對其他類型返回其相應的類型通過cast方法(該方法上的返回值泛型T爲在類創建時確定下來的值),來保證方法最終的返回類型與傳入的classOfT一致

經過層層的調用,最終會調用到如下方法

public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
  boolean isEmpty = true;
  boolean oldLenient = reader.isLenient();
  reader.setLenient(true);
  try {
    reader.peek();
    isEmpty = false;
    TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);
    TypeAdapter<T> typeAdapter = getAdapter(typeToken);
    T object = typeAdapter.read(reader);
    return object;
  } catch (EOFException e) {
    ...
}

上述代碼一共做了以下幾件事:
1.我們傳入的一個StringReader,將會再次被包裝成爲一個Json語法格式的JsonReader對象。
2.通過調用setLenient方法,給Json語法提供更加大的寬容度
3.通過reader.peek方法,先做一次語法檢查,並獲取第一個非空字符,通過這個非空字符來標記下一個解析格式。
4.通過傳入的類型Type,來獲取這個類型對應的TypeToken
5.通過生成的TypeToken來生成對應的適配器
(上面我們說到,Gson的作用,是將Json數據模型往不同平臺上的Java對象轉換,實際上可以算是一種平臺接口的轉換,這裏,Gson用了適配器的方式來實現這套方案)
我們來一步步地看下代碼,代碼一進來,reader就調用了一個peek操作,這是爲什麼呢?我們知道,在流式對象中,peek的目的是爲了查看下一個字符,JsonReader也自然如此。JsonReader通過一次peek先做一個簡單的語法校驗,然後標註當前JsonReader解析的時候將以何種形式解析。

//code 3 JsonReader
public JsonToken peek() throws IOException {
    int p = peeked;
    if (p == PEEKED_NONE) {
      p = doPeek();
    }
   ....
}

peek方法並不像我們之前的流式文件那樣,返回一個真實的數據,而是返回一個當前的解析狀態標識JsonToken。JsonToken是一個枚舉類型,用來標識在Json數據格式中的各種語法單位。而在peek()函數的內部,又調用了一個doPeek()。雖然兩個名字非常相同,但是返回的結果卻是完全不同。doPeek是真是意義上的返回數據,也就是返回一個真實的字符:

//code doPeek()
 private int doPeek() throws IOException {
    int peekStack = stack[stackSize - 1];
....
 if (peekStack == JsonScope.EMPTY_DOCUMENT) {//line 1
      if (lenient) {
        consumeNonExecutePrefix();
      }
      stack[stackSize - 1] = JsonScope.NONEMPTY_DOCUMENT;
      ...
    }
    ....

    int c = nextNonWhitespace(true);//line2
    switch (c) {
   ....
    case '{':
      return peeked = PEEKED_BEGIN_OBJECT;//line3
    default:
      pos--; // Don't consume the first character in a literal value.
    }
   ....
  }

在doPeek()函數中,需要用到一個叫做stack變量的數據,裏面存放的是叫做JsonScope的一堆常量。這是因爲,Gson對Json的解析方式,是採用棧式的解析,按照層次解析的方式,這種層次解析的方式需要用棧來記錄一些先前的狀態。而這個stack的初始值,在一個初始代碼塊中設置:

 private int[] stack = new int[32];
  public int stackSize = 0;
  {
    stack[stackSize++] = JsonScope.EMPTY_DOCUMENT;
  }

可見,stack初始棧頂數據爲EMPTY_DOCUMENT常量。這時候,我們回到doPeek函數中去。我們可以看到:
1.if將調用line1中的方法體。將棧頂數據替換爲NONEMPTY_DOCUMENT狀態
2.在line2中獲取下一個非空白字符,賦值給c變量
3.在line3中將執行case '{'將PEEKED_BEGIN_OBJECT 整型常量付給peeked變量,然後返回。
然後我們返回我們的peek()方法:

int p = peeked;
    if (p == PEEKED_NONE) {
      p = doPeek();
    }
    switch (p) {
    case PEEKED_BEGIN_OBJECT:
      return JsonToken.BEGIN_OBJECT;
}

doPeek方法返回一個整型的常量後,peek方法又通過這個整型常量轉化爲對應的JsonToken變量。或許有些看官就會問了,如果是這樣的話,JsonToken的意義何在呢?你完全可以用返回的peeked變量來代替JsonToken的數據?

非墨暫時先不深入回答這個問題,而是通過代碼來推測一下這種可能性:

 case PEEKED_SINGLE_QUOTED_NAME:
    case PEEKED_DOUBLE_QUOTED_NAME:
    case PEEKED_UNQUOTED_NAME:
      return JsonToken.NAME;

我們可以看到,三種peek出來的數據類型,實際上可能對應一種Json中的標識符,那麼,也就是說peek出來的符號類型跟Json中的標識符,實際上是一種多對應的數據關係,所以不能混用。另外,我們在peek()方法中所生成的這個JsonToken,在Reader中並沒有記錄,也就是說,對於數據的解析,Reader還是關心doPeek方法中生成的中間狀態數據。

我們回到code2中,根據上面的分析,我們已經知道reader.peek()方法實際上是初始了一些數據變量。接下去,fromJson方法將通過TypeToken.get的靜態方法來生成一個TypeToken對象。

public static TypeToken<?> get(Type type) {
    return new TypeToken<Object>(type);
  }

TypeToken的get方式,是一種靜態構造工廠,它將直接返回一個TypeToken對象。

TypeToken(Type type) {
    this.type = $Gson$Types.canonicalize($Gson$Preconditions.checkNotNull(type)/*驗證*/);/*生成Gson內部的type*/
    this.rawType = (Class<? super T>) $Gson$Types.getRawType(this.type);
    this.hashCode = this.type.hashCode();
  }

Gson代碼結構中,以**':1.&#x27;**打頭的類用來標識那些只有靜態方法的工具類: 1.GsonPreconditions:2.Preconditions:用於驗證一些參數信息 2.Gson$Types :相當於類適配器,將Java的Type實現類型轉化爲Gson自己的Type類型實現對象
在TypeToken中,有兩個非常重要的變量,一個是type,一個是rawType。舉個簡單的例子來說明一下這兩個變量的含義:

TypeToken token = new TypeToken<List<User>>(){}

我們通過一個匿名類來生成一個TypeToken對象,這裏我們傳入一個泛型的參數List。那麼這個TypeToken對應的type類型就是List,而對應的rawType就是List。通過這個簡單的理解,我們來看下Gson具體是如何做的:

//code $Gson$Types.java
public static Type canonicalize(Type type) {
    if (type instanceof Class) {
      Class<?> c = (Class<?>) type;
      return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c;

    } else if (type instanceof ParameterizedType) {
      ParameterizedType p = (ParameterizedType) type;
      return new ParameterizedTypeImpl(p.getOwnerType(),
          p.getRawType(), p.getActualTypeArguments());

    } else if (type instanceof GenericArrayType) {
      GenericArrayType g = (GenericArrayType) type;
      return new GenericArrayTypeImpl(g.getGenericComponentType());

    } else if (type instanceof WildcardType) {
      WildcardType w = (WildcardType) type;
      return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds());

    } else {
      // type is either serializable as-is or unsupported
      return type;
    }
  }

Gson通過**GsonGsonTypes**的canonicalize方法,將原本定義在JDK裏面的Type實現,轉化爲自己內部的數據實現。主要還是爲了操作數據的方便。這裏解釋一下涉及泛型的一些函數:
1.getOwnerType: 代表擁有者類型,比如你的類型是一個內部類,那麼這個Type就指向的是你外部類的類型
2.getRawType : 指向泛型的最外部的類型,比如List指向的就是List類型
3.getGenericComponentType : 指向數組成員類型
4.Gson中將Array類型的Class也歸納爲GenericArrayTypeImpl類型
5.getEnclosingClass: 獲得外部類

我們重點來看一下ParameterizedType類型

public ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) {
      // require an owner type if the raw type needs it
      if (rawType instanceof Class<?>) {
        Class<?> rawTypeAsClass = (Class<?>) rawType;
        boolean isStaticOrTopLevelClass = Modifier.isStatic(rawTypeAsClass.getModifiers())
            || rawTypeAsClass.getEnclosingClass() == null;
        checkArgument(ownerType != null || isStaticOrTopLevelClass);//判斷是否靜態內部類
      }
      this.ownerType = ownerType == null ? null : canonicalize(ownerType);
      this.rawType = canonicalize(rawType);
      this.typeArguments = typeArguments.clone();
      for (int t = 0; t < this.typeArguments.length; t++) {
        checkNotNull(this.typeArguments[t]);
        checkNotPrimitive(this.typeArguments[t]);
        this.typeArguments[t] = canonicalize(this.typeArguments[t]);
      }
    }

ParameterizedTypeImpl對象,構造的前半部分代碼,將判斷此類型是否是靜態內部類。爲什麼需要做這一步操作呢?因爲非靜態內部類,需要通過外部類的對象才能生成,而Gson目前還沒有傳入一個外部類對象的接口。
之後,再生成一個外部類的Type變量ownerType,以及最外層類型rawType> 之後,通過遞歸的方式生成typeArguments的類型

我們回到剛纔user的例子:

Gson gson = new Gson();
String strJson = "{name:'david',age:19,room:{roomName:'small',number:1}}";
User u = gson.fromJson(strJson, User.class);

由於User類是一個很純粹的類,因此,在canonicalize方法調用的時候,並不會構建Gson內部的類型,而是會直接返回Class類型。那麼當TypeToken.get(User.class)的時候,返回的就是一個內部持有一個User.class爲Type的TypeToken變量。
這時候我們再回到code2中(Gson.fromJson方法中),在通過TypeToken.get(Type)方法調用以後,將會通過一個叫getAdapter的方法來獲得typeAdapter對象。
TypeAdapter是Gson代碼體系中的重中之重,它承擔了真正意義上的轉換工作。Gson在Adapter的管理上,利用了享元,畢竟,解析類結構有一定的時間消耗,爲了降低這種時間上的開銷,Gson使用了緩衝池來管理這種映射關係。或許讀者有一個問題:既然TypeToken.get方法每次都是利用靜態工廠的方式構造一個新的TypeToken,那麼你在放入cache中並不能起到cache的作用?
答案是:可以的。回答這個問題,我們需要回到TypeToken的源碼:

@Override public final int hashCode() {
    return this.hashCode;
  }

  @Override public final boolean equals(Object o) {
    return o instanceof TypeToken<?>
        && $Gson$Types.equals(type, ((TypeToken<?>) o).type);
  }

如上述代碼顯示,TypeToken利用相同的hashCode和複寫的equals方法,來解決不同對象的衝突問題。好的,我們繼續回到getAdapter方法:

// code Gson.getAdapter
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
    boolean requiresThreadLocalCleanup = false;
    if (threadCalls == null) {
      threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
      calls.set(threadCalls);
      requiresThreadLocalCleanup = true;
    }

當cache中並不存在需要的適配器的時候,並且該線程並不存在有緩衝池對象的時候,Gson將構造一個Map對象,放入線程的中。同事我們還可以發現Gson的Cache的特點:
1.在Gson的Cache管理裏,實際上應用了二級緩衝
2.Gson對象內部有一個緩衝,而Gson對象所在的線程又有一個共享Cache。
3.在不同的線程之間,又使用不同的cache。
是否有某位看官有這樣的疑問,爲什麼在Gson的管理裏會有3級的Cache?

首先,爲什麼Gson自身有一個Cache呢?明明可以直接從線程Cache中獲取?
這個是因爲Gson可能被另外一個線程訪問,而如果有了Gson的對象Cache就可以實現共享。

爲什麼需要多線程之間的Cache?
這個問題非墨是基於一種猜測,多線程間的Cache不一定可以省略,原因是因爲如果Adapter在轉換數據過程中存在有狀態位,很有可能造成數據不同步(但其實這個,完全可以通過拷貝的方式解決。這對提升Gson的效率是很有幫助的)
getAdapter方法之後是方法的核心:

FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
      threadCalls.put(type, call);
      for (TypeAdapterFactory factory : factories) {
        TypeAdapter<T> candidate = factory.create(this, type);
        if (candidate != null) {
          call.setDelegate(candidate);
          typeTokenCache.put(type, candidate);
          return candidate;
        }
      }

Adapter的構造是通過遍歷一個factories集合類來完成的。做法也很簡單,Factory通過匹配傳入的TypeToken類型,然後是否匹配,如果匹配將生成對象,不匹配就返回null。同時,一旦生成Adapter對象,程序立馬返回,說明構造對象是有優先級別的,可能你的AFactory通過規則可以生成對象,BFactory通過規則也可以生成對象,那麼這個時候如果AFactory在BFactory的前面,那麼將優先使用AFactory來構造Adapter。
factories的初始化數據在Gson的構造器裏:

// built-in type adapters that cannot be overridden
    factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);//針對JsonElement類做特別處理
    factories.add(ObjectTypeAdapter.FACTORY);//針對Object類做特殊處理

    // the excluder must precede all adapters that handle user-defined types
    factories.add(excluder);//用於攔截一些不在使用的類型

    // user's type adapters
    factories.addAll(typeAdapterFactories);
    ....
    this.factories = Collections.unmodifiableList(factories);

我們不妨挑一些工廠來看一下,我們來看下excluder這個工廠。excluder是用於攔截一些過期的Gson類型。它的實現類是:Excluder類:

//code Excluder.java
 // function:public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type)
    Class<?> rawType = type.getRawType();
    final boolean skipSerialize = excludeClass(rawType, true);
    final boolean skipDeserialize = excludeClass(rawType, false);
if (!skipSerialize && !skipDeserialize) {
      return null;
    }

代碼中可以看出,Excluder類是通過excludeClass方法,來判斷是否exclude掉該類,我們再看一下excludeClass方法:

public boolean excludeClass(Class<?> clazz, boolean serialize) {
    if (version != Excluder.IGNORE_VERSIONS
        && !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class))) {//判斷類註解
      return true;
    }

    if (!serializeInnerClasses && isInnerClass(clazz)) {//判斷是否是內部類,並且增加忽略內部類標註
      return true;
    }

    if (isAnonymousOrLocal(clazz)) {//判斷是否是匿名類,或者是局部類
      return true;
    }

    List<ExclusionStrategy> list = serialize ? serializationStrategies : deserializationStrategies;
    for (ExclusionStrategy exclusionStrategy : list) {//通過判斷策略來判斷是否忽略類型
      if (exclusionStrategy.shouldSkipClass(clazz)) {
        return true;
      }
    }
    return false;
  }

Gson將會用一堆的策略接口,來判斷你的類是否被skip。當Excluder 確定skip掉你的類的時候,excludeClass將返回true結果。代碼執行之後,將返回一個匿名的TypeAdapter對象:

return new TypeAdapter<T>() {
      /** The delegate is lazily created because it may not be needed, and creating it may fail. */
      private TypeAdapter<T> delegate;

      @Override public T read(JsonReader in) throws IOException {
        if (skipDeserialize) {
          in.skipValue();
          return null;
        }
        return delegate().read(in);
      }

      @Override public void write(JsonWriter out, T value) throws IOException {
        if (skipSerialize) {
          out.nullValue();
          return;
        }
        delegate().write(out, value);
      }

      private TypeAdapter<T> delegate() {
        TypeAdapter<T> d = delegate;
        return d != null
            ? d
            : (delegate = gson.getDelegateAdapter(Excluder.this, type));
      }
    };
  }

而這個匿名的對象,將通過一個代理對象delegate(通過gson.getDelegateAdapter(Excluder.this, type)獲得)來適配對象。

我們回到上面User和ClassRoom的例子,當我們傳入一個User.class類型的時候,Gson會通過ReflectiveTypeAdapterFactory工廠來生產一個Adapter來適配Json對象:

public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
    Class<? super T> raw = type.getRawType();

    if (!Object.class.isAssignableFrom(raw)) {//攔截基本類型
      return null; // it's a primitive!
    }

    ObjectConstructor<T> constructor = constructorConstructor.get(type);//獲取構造器
    return new Adapter<T>(constructor, getBoundFields(gson, type, raw));
  }

我們可以通過上面的代碼得到以下的結論:
1.這個工廠類的將針對所有非基本類型的類型進行攔截,然後通過內部的Adapter類進行轉換
2.而在轉換的過程中,需要傳入一個ObjectConstructor類型的對象用於構造對象。而這個構造器的獲取,源自於一個constructorConstructor的變量。
這裏,我們應該不論從名字上還是從什麼方面,都能很清楚的知道ObjectConstructor和constructorConstructor的用意。
那麼爲什麼需要一個Constructor的構造器呢?你直接通過類型反射不就完成類型的構造?
原因是因爲Gson是支持接口類型,比如List<?>這種集合類。而接口類型轉化爲Java的實際對象的方式主要有兩種:
一種是常見的提供實現類,另一種是生成接口類型的動態代理。而通過動態代理的方案明顯不合適,因此Gson在處理這種接口類型的時候,默認提供了一些實現類。
constructorConstructor對象在ReflectiveTypeAdapterFactory構造的時候傳入,而所有TypeAdapter的構造工廠都在Gson對象初始化的時候構造。

Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingPolicy,
      final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
      boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
      boolean prettyPrinting, boolean serializeSpecialFloatingPointValues,
      LongSerializationPolicy longSerializationPolicy,
      List<TypeAdapterFactory> typeAdapterFactories) {
    this.constructorConstructor = new ConstructorConstructor(instanceCreators);
...
}

constructorConstructor的構造,傳入了一個instanceCreators對象,實際上,這個對象是一個享元對象。但默認的情況下,這個對象爲空,如果你有自己構造一個對象的需求,可以注入這個對象。那麼,Gson會優先選擇你注入的這個對象構造器來改造最終對象,爲了說明這點,我們來看下ConstructorConstructor的
ObjectConstructor get(TypeToken typeToken)方法:

public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {
    final Type type = typeToken.getType();
    final Class<? super T> rawType = typeToken.getRawType();

    // first try an instance creator

    @SuppressWarnings("unchecked") // types must agree
    final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);//先在instanceCreators 查找是否有對應的構造器
    if (typeCreator != null) {
      return new ObjectConstructor<T>() {
        public T construct() {
          return typeCreator.createInstance(type);
        }
      };
    }

    // Next try raw type match for instance creators
    @SuppressWarnings("unchecked") // types must agree
    final InstanceCreator<T> rawTypeCreator =
        (InstanceCreator<T>) instanceCreators.get(rawType);
    if (rawTypeCreator != null) {
      return new ObjectConstructor<T>() {
        public T construct() {
          return rawTypeCreator.createInstance(type);
        }
      };
    }
//如果沒有找到構造器,將使用默認構造器
    ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);
    if (defaultConstructor != null) {
      return defaultConstructor;
    }

    ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);
    if (defaultImplementation != null) {
      return defaultImplementation;
    }

    // finally try unsafe
    return newUnsafeAllocator(type, rawType);
  }

代碼剛開始,將通過instanceCreators攔截,一旦攔截失敗,如果是普通類,將使用默認構造器,如果是接口類將通過newDefaultImplementationConstructor方法,來獲取默認接口實現類。

private <T> ObjectConstructor<T> newDefaultConstructor(Class<? super T> rawType) {
    try {
      final Constructor<? super T> constructor = rawType.getDeclaredConstructor();
      if (!constructor.isAccessible()) {
        constructor.setAccessible(true);
      }
      return new ObjectConstructor<T>() {
        @SuppressWarnings("unchecked") // T is the same raw type as is requested
        public T construct() {
          try {
            Object[] args = null;
            return (T) constructor.newInstance(args);
            ....
    }
  }

可見,普通類的構造,Gson將通過一個無參數的構造器來反射調用。而非普通類型將調用newDefaultImplementationConstructor方法來生成一些默認的構造器

private <T> ObjectConstructor<T> newDefaultImplementationConstructor(
      final Type type, Class<? super T> rawType) {//集合類檢測
    if (Collection.class.isAssignableFrom(rawType)) {
      if (SortedSet.class.isAssignableFrom(rawType)) {
        return new ObjectConstructor<T>() {
          public T construct() {
            return (T) new TreeSet<Object>();//排序集合實現類
          }
        };
      } else if (EnumSet.class.isAssignableFrom(rawType)) {
        return new ObjectConstructor<T>() {
          @SuppressWarnings("rawtypes")
          public T construct() {
            if (type instanceof ParameterizedType) {
              Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
              if (elementType instanceof Class) {
                return (T) EnumSet.noneOf((Class)elementType);
              } else {
                throw new JsonIOException("Invalid EnumSet type: " + type.toString());
              }
            } else {
              throw new JsonIOException("Invalid EnumSet type: " + type.toString());
            }
          }
        };
      } else if (Set.class.isAssignableFrom(rawType)) {
        return new ObjectConstructor<T>() {
          public T construct() {
            return (T) new LinkedHashSet<Object>();//集合類默認實現
          }
        };
      } else if (Queue.class.isAssignableFrom(rawType)) {
        return new ObjectConstructor<T>() {
          public T construct() {
            return (T) new LinkedList<Object>();//隊列默認實現
          }
        };
      } else {
        return new ObjectConstructor<T>() {
          public T construct() {
            return (T) new ArrayList<Object>();//否則統一用ArrayList來實現集合類
          }
        };
      }
    }

    if (Map.class.isAssignableFrom(rawType)) {
      if (SortedMap.class.isAssignableFrom(rawType)) {
        return new ObjectConstructor<T>() {
          public T construct() {
            return (T) new TreeMap<Object, Object>();
          }
        };
      } else if (type instanceof ParameterizedType && !(String.class.isAssignableFrom(
          TypeToken.get(((ParameterizedType) type).getActualTypeArguments()[0]).getRawType()))) {
        return new ObjectConstructor<T>() {
          public T construct() {
            return (T) new LinkedHashMap<Object, Object>();
          }
        };
      } else {
        return new ObjectConstructor<T>() {
          public T construct() {
            return (T) new LinkedTreeMap<String, Object>();
          }
        };
      }
    }

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