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;
  }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章