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代碼結構中,以**'GsonGson$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通過**Types**的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;
}