【原標(biāo)題:bigdecimal類解決Java精度問題 Java 工程師成神之路】前言之前一段時(shí)間,準(zhǔn)備把糗百的項(xiàng)目中json解析的模塊中的原生Json解析換成gson解析,工作比較繁雜,坑多,因此為了防止出錯(cuò),我還對(duì)Gson做了一個(gè)源碼分析。這一篇就是Gson源碼分析的總結(jié),同時(shí)對(duì)Gson內(nèi)部運(yùn)用的設(shè)計(jì)模式也進(jìn)行了總結(jié),相信了解了它的源碼和運(yùn)行機(jī)制,對(duì)于使用Gson的使用會(huì)更有幫助。
Gson簡(jiǎn)介
Gson,就是幫助我們完成序列化和反序列化的工作的一個(gè)庫(kù)。
日常用法
UserInfouserInfo=getUserInfo();
Gsongson=newGson();
StringjsonStr=gson.toJson(userInfo);//序列化
UserInfouser=gson.fromJson(jsonStr,UserInfo.class);//反序列化
實(shí)際上我們用的最多的是Gson的反序列化,主要在解析服務(wù)器返回的json串。因此,后面的文章也會(huì)以Gson中的反序列化的過程為主來分析代碼。
在分析之前,我們先做個(gè)簡(jiǎn)單的猜想,要如何實(shí)現(xiàn)反序列化的流程的,Gson大體會(huì)做一下這三件事:
反射創(chuàng)建該類型的對(duì)象
把json中對(duì)應(yīng)的值賦給對(duì)象對(duì)應(yīng)的屬性
返回該對(duì)象。
事實(shí)上,Gson想要把json數(shù)據(jù)反序列化基本都逃不掉這三個(gè)步驟,但是這三個(gè)步驟就像小品里分三步把大象裝進(jìn)冰箱一樣。我們知道最復(fù)雜的一步就是把大象裝進(jìn)去,畢竟,開冰箱門或者關(guān)冰箱門大家都會(huì)的嘛。在Gson中,復(fù)雜的就是怎樣把json中對(duì)應(yīng)數(shù)據(jù)放入對(duì)應(yīng)的屬性中。而這個(gè)問題的答案就是Gson的TypeAdapter。
Gson核心:TypeAdapterTypeAdapter是Gson的核心,它的意思是類型適配器,而說到適配器,大家都會(huì)想到適配器模式,沒錯(cuò),這個(gè)TypeAdapter的設(shè)計(jì)這確實(shí)是一個(gè)適配器模式,因?yàn)镴son數(shù)據(jù)接口和Type的接口兩者是無法兼容,因此TypeAdapter就是來實(shí)現(xiàn)兼容,把json數(shù)據(jù)讀到Type中,把Type中的數(shù)據(jù)寫入到Json里。
publicabstractclassTypeAdapter
//JsonWriter代表Json數(shù)據(jù),T則是對(duì)應(yīng)的Type的對(duì)象
publicabstractvoidwrite(JsonWriterout,Tvalue)throwsIOException;
//JsonWriter代表Json數(shù)據(jù),T則是對(duì)應(yīng)的Type的對(duì)象
publicabstractTread(JsonReaderin)throwsIOException;
...
...
...
}
簡(jiǎn)單而言,TypeAdapter的作用就是針對(duì)Type進(jìn)行適配,保證把json數(shù)據(jù)讀到Type中,或者把Type中的數(shù)據(jù)寫入到Json里
Type和TypeAdapter的對(duì)應(yīng)關(guān)系Gson會(huì)為每一種類型創(chuàng)建一個(gè)TypeAdapter,同樣的,每一個(gè)Type都對(duì)應(yīng)唯一一個(gè)TypeAdapter
而所有Type(類型),在Gson中又可以分為基本類型和復(fù)合類型(非基本類型)
基本類型(Integer,String,Uri,Url,Calendar…):這里的基本類型不僅包括Java的基本數(shù)據(jù)類型,還有很多其他的數(shù)據(jù)類型
復(fù)合類型(非基本類型):即除了基本類型之外的類型,往往是我們自定義的一些業(yè)務(wù)相關(guān)的JavaBean,比如User,Article…..等等。
這里的基本類型和復(fù)合類型(非基本類型)是筆者定義的詞匯,因?yàn)檫@樣定義對(duì)于讀者理解Gson源碼和運(yùn)行機(jī)制更有幫助。
如上圖,每一種基本類型都會(huì)創(chuàng)建一個(gè)TypeAdapter來適配它們,而所有的復(fù)合類型(即我們自己定義的各種JavaBean)都會(huì)由ReflectiveTypeAdapter來完成適配
TypeAdapter和Gson運(yùn)行機(jī)制既然講到了每種Type都有對(duì)應(yīng)的TypeAdapter,那么為什么說TypeAdapter是Gson的核心呢?我們可以看看Gson到底是如何實(shí)現(xiàn)Json解析的呢,下圖是Gson完成json解析的抽象簡(jiǎn)化的流程圖:
如上圖,如果是基本類型,那么對(duì)應(yīng)的TypeAdapter就可以直接讀寫Json串,如果是復(fù)合類型,ReflectiveTypeAdapter會(huì)反射創(chuàng)建該類型的對(duì)象,并逐個(gè)分析其內(nèi)部的屬性的類型,然后重復(fù)上述工作。直至所有的屬性都是Gson認(rèn)定的基本類型并完成讀寫工作。
TypeAdapter源碼分析當(dāng)類型是復(fù)合類型的時(shí)候,Gson會(huì)創(chuàng)建ReflectiveTypeAdapter,我們可以看看這個(gè)Adapter的源碼:
//創(chuàng)建ReflectiveTypeAdapter
newAdapter
...
...
/**
*ReflectiveTypeAdapter是ReflectiveTypeAdapterFactory的內(nèi)部類,其實(shí)際的類名就是Adapter
*本文只是為了區(qū)別其他的TypeAdapter而叫它ReflectiveTypeAdapter
**/
publicstaticfinalclassAdapter
//該復(fù)合類型的構(gòu)造器,用于反射創(chuàng)建對(duì)象
privatefinalObjectConstructor
//該類型內(nèi)部的所有的Filed屬性,都通過map存儲(chǔ)起來
privatefinalMap
Adapter(ObjectConstructor
this.constructor=constructor;
this.boundFields=boundFields;
}
//JsonReader是Gson封裝的對(duì)Json相關(guān)的操作類,可以依次讀取json數(shù)據(jù)
//類似的可以參考Android封裝的對(duì)XML數(shù)據(jù)解析的操作類XmlPullParser
@OverridepublicTread(JsonReaderin)throwsIOException{
if(in.peek()==JsonToken.NULL){
in.nextNull();
returnnull;
}
Tinstance=constructor.construct();
try{
in.beginObject();//從“{”開始讀取
while(in.hasNext()){
Stringname=in.nextName();//開始逐個(gè)讀取json串中的key
BoundFieldfield=boundFields.get(name);//通過key尋找對(duì)應(yīng)的屬性
if(field==null||!field.deserialized){
in.skipValue();
}else{
field.read(in,instance);//將json串的讀取委托給了各個(gè)屬性
}
}
}catch(IllegalStateExceptione){
thrownewJsonSyntaxException(e);
}catch(IllegalAccessExceptione){
thrownewAssertionError(e);
}
in.endObject();//到對(duì)應(yīng)的“}”結(jié)束
returninstance;
}
...
...
}
Gson內(nèi)部并沒有ReflectiveTypeAdapter這個(gè)類,它其實(shí)際上是ReflectiveTypeAdapterFactory類一個(gè)名叫Adapter的內(nèi)部類,叫它ReflectiveTypeAdapter是為了表意明確。
我們看到,ReflectiveTypeAdapter內(nèi)部會(huì)首先創(chuàng)建該類型的對(duì)象,然后遍歷該對(duì)象內(nèi)部的所有屬性,接著把json傳的讀去委托給了各個(gè)屬性。
被委托的BoundField內(nèi)部又是如何做的呢?BoundField這個(gè)類,是對(duì)Filed相關(guān)操作的封裝,我們來看看BoundField是如何創(chuàng)建的,以及內(nèi)部的工作原理。
//創(chuàng)建ReflectiveTypeAdaptergetBoundFields獲取該類型所有的屬性
newAdapter
...
...
privateMap
//創(chuàng)建一個(gè)Map結(jié)構(gòu),存放所有的BoundField
Map
if(raw.isInterface()){
returnresult;
}
TypedeclaredType=type.getType();
while(raw!=Object.class){//如果類型是Object則結(jié)束循環(huán)
Field[]fields=raw.getDeclaredFields();//獲取該類型的所有的內(nèi)部屬性
for(Fieldfield:fields){
booleanserialize=excludeField(field,true);
booleandeserialize=excludeField(field,false);
if(!serialize&&!deserialize){
continue;
}
accessor.makeAccessible(field);
TypefieldType=$Gson$Types.resolve(type.getType(),raw,field.getGenericType());
List
BoundFieldprevious=null;
for(inti=0,size=fieldNames.size();i Stringname=fieldNames.get(i); //多個(gè)解析名,第一作為默認(rèn)的序列化名稱 if(i!=0)serialize=false;//onlyserializethedefaultname //創(chuàng)建BoundField BoundFieldboundField=createBoundField(context,field,name, TypeToken.get(fieldType),serialize,deserialize); //將BoundField放入Map中,獲取被替換掉的value(如果有的話) BoundFieldreplaced=result.put(name,boundField); //做好記錄 if(previous==null)previous=replaced; } if(previous!=null){ //如果previous!=null證明出現(xiàn)了兩個(gè)相同的Filedname,直接拋出錯(cuò)誤 //注:Gson不允許定義兩個(gè)相同的名稱的屬性(父類和子類之間可能出現(xiàn)) thrownewIllegalArgumentException(declaredType +"declaresmultipleJSONfieldsnamed"+previous.name); } } type=TypeToken.get($Gson$Types.resolve(type.getType(),raw,raw.getGenericSuperclass())); raw=type.getRawType();//獲取父類類型,最終會(huì)索引到Object.因?yàn)镺bject是所有對(duì)象的父類 } returnresult; } 上面這段代碼的主要工作就是,找到該類型內(nèi)部的所有屬性,并嘗試逐一封裝成BoundField。 //根據(jù)每個(gè)Filed創(chuàng)建BoundField(封裝Filed讀寫操作) privateReflectiveTypeAdapterFactory.BoundFieldcreateBoundField( finalGsoncontext,finalFieldfield,finalStringname, finalTypeTokenfieldType,booleanserialize,booleandeserialize){ //是否是原始數(shù)據(jù)類型(int,boolean,float...) finalbooleanisPrimitive=Primitives.isPrimitive(fieldType.getRawType()); ... ... if(mapped==null){ //Gson嘗試獲取該類型的TypeAdapter,這個(gè)方法我們后面也會(huì)繼續(xù)提到。 mapped=context.getAdapter(fieldType); } //final變量,便于內(nèi)部類使用 finalTypeAdaptertypeAdapter=mapped; returnnewReflectiveTypeAdapterFactory.BoundField(name,serialize,deserialize){ ... ... //ReflectiveTypeAdapter委托的Json讀操作會(huì)調(diào)用到這里 @Overridevoidread(JsonReaderreader,Objectvalue) throwsIOException,IllegalAccessException{ //通過該屬性的類型對(duì)應(yīng)的TypeAdapter嘗試讀取json串 //如果是基礎(chǔ)類型,則直接讀取, //如果是復(fù)合類型則遞歸之前的流程 ObjectfieldValue=typeAdapter.read(reader); if(fieldValue!=null||!isPrimitive){ field.set(value,fieldValue);//更新filed值 } } @OverridepublicbooleanwriteField(Objectvalue)throwsIOException,IllegalAccessException{ if(!serialized)returnfalse; ObjectfieldValue=field.get(value); returnfieldValue!=value;//avoidrecursionforexampleforThrowable.cause } }; } 假設(shè)該復(fù)合類型中所有的屬性的類型是String,則屬性所對(duì)應(yīng)的TypeAdapter以及其讀寫方式如下: publicstaticfinalTypeAdapter @Override publicStringread(JsonReaderin)throwsIOException{ JsonTokenpeek=in.peek();//獲取下一個(gè)jsontoken而不消耗它 if(peek==JsonToken.NULL){ in.nextNull(); returnnull; } /*coercebooleanstostringsforbackwardscompatibility*/ if(peek==JsonToken.BOOLEAN){ returnBoolean.toString(in.nextBoolean());//如果時(shí)布爾值,則轉(zhuǎn)化為String } returnin.nextString();//從json串中獲取這個(gè)String類型的value并消耗它 } @Override publicvoidwrite(JsonWriterout,Stringvalue)throwsIOException{ out.value(value);//不做任何處理直接寫入Json串 } } 到這里,關(guān)于Gson的TypeAdapter的原理也就講得差不多了,回顧一下,因?yàn)門ype有兩類,對(duì)應(yīng)的TypeAdapter也有兩類,一類是ReflectiveTypeAdapter,針對(duì)復(fù)合類型,它的作用是把復(fù)合類型拆解成基本類型,另一類是針對(duì)基本類型的TypeAdapter,實(shí)現(xiàn)對(duì)應(yīng)基本類型的Json串讀寫工作。而Gson本質(zhì)上就是按照這兩類TypeAdapter來完成Json解析的。 可以說,到這里,我們現(xiàn)在對(duì)Gson的基本工作流程有了一個(gè)基本的認(rèn)識(shí)。 再一次分析Gson的執(zhí)行邏輯事實(shí)上,文章到這里結(jié)合上面的源碼剖析和簡(jiǎn)化流程圖,我們已經(jīng)可以比較比較真實(shí)的分析出Gson的執(zhí)行邏輯了。 Gson反序列化的日常用法: UserInfouserInfo=getUserInfo(); Gsongson=newGson(); StringjsonStr=getJsonData(); UserInfouser=gson.fromJson(jsonStr,UserInfo.class);//反序列化 gson.fromJson(jsonStr,UserInfo.class)方法內(nèi)部真實(shí)的代碼執(zhí)行流程大致如下: 對(duì)jsonStr,UserInfo.class這兩個(gè)數(shù)據(jù)進(jìn)行封裝 通過UserInfo.class這個(gè)Type來獲取它對(duì)應(yīng)的TypeAdapter 拿到對(duì)應(yīng)的TypeAdapter(ReflectiveTypeAdapterFactor),并執(zhí)行讀取json的操作 返回UserInfo這個(gè)類型的對(duì)象。 我們描述的這個(gè)流程和Gson代碼真實(shí)的執(zhí)行流程已經(jīng)沒太大的區(qū)別了。 TypeAdapter的創(chuàng)建與工廠模式Gson中除了適配器模式之外最重要的設(shè)計(jì)模式,可能就是工廠模式吧。因?yàn)镚son中眾多的TypeAdapter都是通過工廠模式統(tǒng)一創(chuàng)建的: publicinterfaceTypeAdapterFactory{ //創(chuàng)建TypeAdapter的接口 } 我們可以看看ReflectiveTypeAdapterFactory的實(shí)現(xiàn) //ReflectiveTypeAdapterFactory的實(shí)現(xiàn) publicfinalclassReflectiveTypeAdapterFactoryimplementsTypeAdapterFactory{ @Overridepublic Classraw=type.getRawType(); //只要是Object的子類,就能匹配上 if(!Object.class.isAssignableFrom(raw)){ //it'saprimitive! returnnull; } ObjectConstructor returnnewAdapter } } Gson在其構(gòu)造方法中,就提前把所有的TypeAdapterFactory放在緩存列表中。 Gson(finalExcluderexcluder,finalFieldNamingStrategyfieldNamingStrategy, finalMap booleancomplexMapKeySerialization,booleangenerateNonExecutableGson,booleanhtmlSafe, booleanprettyPrinting,booleanlenient,booleanserializeSpecialFloatingPointValues, LongSerializationPolicylongSerializationPolicy,StringdatePattern,intdateStyle, inttimeStyle,List List List ... ... ... List //built-intypeadaptersthatcannotbeoverridden factories.add(TypeAdapters.JSON_ELEMENT_FACTORY); factories.add(ObjectTypeAdapter.FACTORY); //theexcludermustprecedealladaptersthathandleuser-definedtypes factories.add(excluder); //userstypeadapters factories.addAll(factoriesToBeAdded); //typeadaptersforbasicplatformtypes 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 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); //typeadaptersforcompositeanduser-definedtypes factories.add(newCollectionTypeAdapterFactory(constructorConstructor)); factories.add(newMapTypeAdapterFactory(constructorConstructor,complexMapKeySerialization)); this.jsonAdapterFactory=newJsonAdapterAnnotationTypeAdapterFactory(constructorConstructor); factories.add(jsonAdapterFactory); factories.add(TypeAdapters.ENUM_FACTORY); //注意,ReflectiveTypeAdapterFactor是要最后添加的 factories.add(newReflectiveTypeAdapterFactory( constructorConstructor,fieldNamingStrategy,excluder,jsonAdapterFactory)); this.factories=Collections.unmodifiableList(factories); } 這里我們能夠看到,ReflectiveTypeAdapterFactor最后被添加進(jìn)去的,因?yàn)檫@里的添加順序是有講究的。我們看看getAdapter(type)方法就能知道。 getAdapter(type)這個(gè)方法就是gson通過type尋找到對(duì)應(yīng)的TypeAdapter,這是Gson中非常重要的一個(gè)方法。 //通過Type獲取TypeAdapter public try{ //遍歷緩存中所有的TypeAdapterFactory, for(TypeAdapterFactoryfactory:factories){ //如果類型匹配,則create()將會(huì)返回一個(gè)TypeAdapter,否則為nulll TypeAdapter if(candidate!=null){ //candidate不為null,證明找到類型匹配的TypeAdapter. returncandidate; } } thrownewIllegalArgumentException("GSON("+GsonBuildConfig.VERSION+")cannothandle"+type); } } ReflectiveTypeAdapterFactory之所以在緩存列表的最后一個(gè),就是因?yàn)樗芷ヅ鋷缀跞魏晤愋?,因此,我們?yōu)橐粋€(gè)類型遍歷時(shí),只能先判斷它是不是基本類型,如果都不成功,最后再使用ReflectiveTypeAdapterFactor進(jìn)行判斷。 這就是Gson中用到的工廠模式。 關(guān)于代碼的難點(diǎn)我們重新回到getAdapter(type)這個(gè)方法,這個(gè)方法里面有一些比較難理解的代碼 //通過Type獲取TypeAdapter public //typeTokenCache是Gson的一個(gè)Map類型的緩存結(jié)構(gòu) //0,首先嘗試從緩存中獲取是否有對(duì)應(yīng)的TypeAdapter TypeAdaptercached=typeTokenCache.get(type==null?NULL_KEY_SURROGATE:type); if(cached!=null){ return(TypeAdapter } //1,alls是Gson內(nèi)部的ThreadLocal變量,用于保存一個(gè)Map對(duì)象 //map對(duì)象也緩存了一種FutureTypeAdapter Map booleanrequiresThreadLocalCleanup=false; if(threadCalls==null){ threadCalls=newHashMap calls.set(threadCalls); requiresThreadLocalCleanup=true; } //2,如果從ThreadLocal內(nèi)部的Map中找到緩存,則直接返回 //thekeyandvaluetypeparametersalwaysagree FutureTypeAdapter if(ongoingCall!=null){ returnongoingCall; } try{ 創(chuàng)建一個(gè)FutureTypeAdapter FutureTypeAdapter //緩存 threadCalls.put(type,call); for(TypeAdapterFactoryfactory:factories){ //遍歷所有的TypeAdapterFactory TypeAdapter if(candidate!=null){ //3,設(shè)置委托的TypeAdapter call.setDelegate(candidate); //緩存到Gson內(nèi)部的Map中, typeTokenCache.put(type,candidate); returncandidate; } } //如果遍歷都沒有找到對(duì)應(yīng)的TypeAdapter,直接拋出異常 thrownewIllegalArgumentException("GSON("+GsonBuildConfig.VERSION+")cannothandle"+type); }finally{ //4,移除threadCalls內(nèi)部緩存的FutureTypeAdapter threadCalls.remove(type); if(requiresThreadLocalCleanup){ //ThreadLocal移除該線程環(huán)境中的Map calls.remove(); } } } 上述代碼比較難以理解的地方我標(biāo)注了序號(hào),用于后面解釋代碼 方法里出現(xiàn)了FutureTypeAdapter這個(gè)TypeAdapter,似乎很奇怪,因?yàn)樗鼪]有FutureTypeAdapterFactory這個(gè)工廠類,我們先來看看 FutureTypeAdapter的內(nèi)部構(gòu)造 staticclassFutureTypeAdapter privateTypeAdapter publicvoidsetDelegate(TypeAdapter if(delegate!=null){ thrownewAssertionError(); } delegate=typeAdapter; } @OverridepublicTread(JsonReaderin)throwsIOException{ if(delegate==null){ thrownewIllegalStateException(); } returndelegate.read(in); } @Overridepublicvoidwrite(JsonWriterout,Tvalue)throwsIOException{ if(delegate==null){ thrownewIllegalStateException(); } delegate.write(out,value); } } 這是一個(gè)明顯的委派模式(也可稱為代理模式)的包裝類。我們都知道委托模式的功能是:隱藏代碼具體實(shí)現(xiàn),通過組合的方式同樣的功能,避開繼承帶來的問題。但是在這里使用委派模式似乎并不是基于這些考慮。而是為了避免陷入無限遞歸導(dǎo)致對(duì)棧溢出的崩潰。 為什么這么說呢?我們來舉個(gè)例子: //定義一個(gè)帖子的實(shí)體 publicclassArticle{ //表示帖子中鏈接到其他的帖子 publicArticlelinkedArticle; ..... ..... ..... } Article類型中有一個(gè)linkedArticle屬性,它的類型還是Article,根據(jù)我們之前總結(jié)的簡(jiǎn)化流程圖: 你會(huì)發(fā)現(xiàn)這里有一個(gè)死循環(huán),或者說無法終結(jié)的遞歸。為了避免這個(gè)問題,所以先創(chuàng)建一個(gè)代理類,等到遞歸遇到同樣的類型時(shí)直接復(fù)用返回,避免無限遞歸。也就是注釋2那段代碼的用意,在注釋3處,再將創(chuàng)建成功的TypeAdapter設(shè)置到代理類中。就基本解決這個(gè)問題了。 當(dāng)然說基本解決,是因?yàn)檫€要考慮多線程的環(huán)境,所以就出現(xiàn)了ThreadLocal這個(gè)線程局部變量,這保證了它只會(huì)在單個(gè)線程中緩存,而且會(huì)在單次Json解析完成后移出緩存。見上文注釋1和注釋4。這是因?yàn)闊o限遞歸只會(huì)發(fā)生在單次Json解析中,而且Gson內(nèi)部已經(jīng)有了一個(gè)TypeAdapterde 全局緩存(typeTokenCache),見注釋0. ? 潛在的遞歸循環(huán): gson.getAdapter(type) ---> (ReflectiveTypeAdapterFactory)factory.create(this, type) ---> getBoundFields() ---> createBoundField() ---> (Gson)context.getAdapter(fieldType) 關(guān)于Gson自定義解析上文只講到了Gson自己內(nèi)部是如何實(shí)現(xiàn)Json解析的,其實(shí)Gson也提供了一些自定義解析的接口。主要是兩種: 自己實(shí)現(xiàn)繼承TypeAdapter 實(shí)現(xiàn)JsonSerializer/JsonDeserializer接口 那么,兩者有什么區(qū)別呢? 追求效率更高,選第一種,想要操作更簡(jiǎn)單,實(shí)現(xiàn)更靈活,選第二種。 為什么這么說?舉個(gè)例子,假設(shè)我們需要為Article這個(gè)JavaBean自定義解析,如果我們選擇繼承TypeAdapter的話,需要先實(shí)現(xiàn)TypeAdapter,然后注冊(cè)。 //繼承TypeAdapter,實(shí)現(xiàn)抽象方法 publicclassArticleTypeAdapterextendsTypeAdapter @Override publicvoidwrite(JsonWriterout,Articlevalue)throwsIOException{ //實(shí)現(xiàn)把Article中的實(shí)體數(shù)據(jù)的寫入到JsonWriter中,實(shí)現(xiàn)序列化 } @Override publicArticleread(JsonReaderin)throwsIOException{ //需要?jiǎng)?chuàng)建Article對(duì)象 //把JsonReader中的json串讀出來,并設(shè)置到Article對(duì)象中 returnnull; } } ... ... //注冊(cè) GsonmGson=newGsonBuilder() .registerTypeAdapter(Article.class,newArticleTypeAdapter<>())//實(shí)際上注冊(cè)到Gson的factories列表中 .create(); 這樣就實(shí)現(xiàn)了自定義的Json解析,這種方式的讀寫效率很高,但是不太靈活,因?yàn)楸仨氁瑫r(shí)實(shí)現(xiàn)序列化和反序列化的工作。 而實(shí)現(xiàn)JsonSerializer/JsonDeserializer接口這種方式相對(duì)更簡(jiǎn)單 //JsonSerializer(json序列話)/JsonDeserializer(反序列化)可按需實(shí)現(xiàn) publicclassArticleTypeAdapterimplementsJsonDeserializer @Override publicArticledeserialize(JsonElementjson,TypetypeOfT,JsonDeserializationContextcontext)throwsJsonParseException{ //需要?jiǎng)?chuàng)建Article對(duì)象 //并從JsonElement中把封裝好的Json數(shù)據(jù)結(jié)構(gòu)讀出來,并設(shè)置到Article對(duì)象中 returnnull; } } //注冊(cè) GsonmGson=newGsonBuilder() .registerTypeAdapter(Article.class,newArticleTypeAdapter<>())//實(shí)際上注冊(cè)到Gson的factories列表中 .create(); 我們可以看到,兩者的區(qū)別,是后者更加靈活,序列化/返序列化可按需選擇,而且它使用了JsonElement對(duì)Json數(shù)據(jù)進(jìn)行再封裝,從而使我們操作Json數(shù)據(jù)更加簡(jiǎn)單。不過正是因?yàn)槭褂昧?JsonElement這種對(duì)Json數(shù)據(jù)再封裝的類,而不是更加原始的JsonReader導(dǎo)致了代碼執(zhí)行效率的降低。 如上圖所示,本質(zhì)上就是多了一個(gè)中間層,導(dǎo)致解析效率的降低。不過話說回來,只要不是非常大批量復(fù)雜結(jié)構(gòu)的連續(xù)解析,這種效率差異我們可以忽略不計(jì),因此日常的開發(fā),大家通過JsonSerializer/JsonDeserializer接口來實(shí)現(xiàn)自定義解析是一個(gè)相對(duì)更好的選擇。