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.
*
* wrap(int.class) == Integer.class
* wrap(Integer.class) == Integer.class
* wrap(String.class) == String.class
*
*/
public static <T> Class<T> wrap(Class<T> type) {
// cast is safe: long.class and Long.class are both of type Class
@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. '**打头的类用来标识那些只有静态方法的工具类: 1. ′∗∗打头的类用来标识那些只有静态方法的工具类:1.Gson P r e c o n d i t i o n s : 用 于 验 证 一 些 参 数 信 息 2. Preconditions:用于验证一些参数信息 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通过** G s o n Gson GsonTypes**的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 TypeAdapter create(final Gson gson, final TypeToken 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;
}