作者簡(jiǎn)介:ASCE1885, 《Android 高級(jí)進(jìn)階》作者。
本文由于潛在的商業(yè)目的涡上,未經(jīng)授權(quán)不開(kāi)放全文轉(zhuǎn)載許可,謝謝拒名!
本文分析的源碼版本已經(jīng) fork 到我的 Github吩愧。
通過(guò)前面一篇文章的介紹,我們知道 Serial 框架的核心是 Serializer 類(lèi)增显,對(duì)象的序列化和反序列化都是通過(guò)重寫(xiě)這個(gè)類(lèi)的方法實(shí)現(xiàn)的雁佳,因此我們就以 Serializer 類(lèi)為起點(diǎn)來(lái)開(kāi)始源碼的剖析,首先來(lái)看下這個(gè)類(lèi)的繼承體系:
讀過(guò)前面一篇文章的同學(xué)對(duì)這幾個(gè)類(lèi)應(yīng)該都有印象同云,這里再簡(jiǎn)單總結(jié)一下:
- Serializer:抽象基類(lèi)糖权,一切的開(kāi)始
- ObjectSerializer:通過(guò)在序列化時(shí)增加版本號(hào)信息從而提供向后兼容性
- BuilderSerializer:繼承自 ObjectSerializer,支持在反序列化時(shí)通過(guò) Builder 模式構(gòu)造對(duì)象
- ValueSerializer:不包含版本號(hào)信息炸站,只處理簡(jiǎn)單數(shù)據(jù)類(lèi)型星澳,不考慮向后兼容性
同時(shí),為了讓框架使用者少寫(xiě)樣板代碼旱易,Serial 還提供 CoreSerializers 和 CollectionSerializers 兩個(gè)類(lèi)禁偎,分別針對(duì)常用的數(shù)據(jù)類(lèi)型和集合定義了一系列默認(rèn) Serializer 類(lèi)。下面我們來(lái)一一分析咒唆。
Serializer
所有 Serializer 的抽象基類(lèi)届垫,定義了最基礎(chǔ)的序列化和反序列化整體框架,我們直接來(lái)看代碼和注釋?zhuān)?/p>
public abstract class Serializer<T> {
/**
* 序列化方法
* @param context 序列化上下文信息
* @param output 序列化輸出流
* @param object 要序列化的對(duì)象實(shí)例
* @throws IOException
*/
public abstract void serialize(@NotNull SerializationContext context,
@NotNull SerializerOutput output, @Nullable T object) throws IOException;
/**
* 反序列化方法全释,反序列化后生成的對(duì)象可能為空
* @param context 序列化上下文信息
* @param input 序列化輸入流
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
@Nullable
public abstract T deserialize(@NotNull SerializationContext context,
@NotNull SerializerInput input) throws IOException, ClassNotFoundException;
/**
* 當(dāng)反序列化后生成的對(duì)象為空時(shí)將拋出異常
* @param context 序列化上下文信息
* @param input 序列化輸入流
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
@NotNull
public final T deserializeNotNull(@NotNull SerializationContext context,
@NotNull SerializerInput input) throws IOException, ClassNotFoundException {
final T deserializedObject = deserialize(context, input);
return InternalSerialUtils.checkIsNotNull(deserializedObject);
}
}
其中涉及到其他幾個(gè)重要的類(lèi):
- SerializationContext:序列化相關(guān)上下文信息装处,下面會(huì)進(jìn)一步介紹
- SerializerInput:序列化輸入流,從序列化后的數(shù)據(jù)中讀取指定類(lèi)型信息的通道,反序列化時(shí)使用妄迁,我們將會(huì)在下一篇文章集中介紹寝蹈,在這里讀者只需要理解它的作用就行
- SerializerOutput:序列化輸出流,將對(duì)象指定類(lèi)型屬性信息寫(xiě)入到其他介質(zhì)(磁盤(pán)等)中的通道登淘,序列化時(shí)使用箫老,同樣會(huì)在下一篇文章介紹
SerializationContext 用于保存序列化過(guò)程中的環(huán)境信息,目前提供兩個(gè)方法分別來(lái)判斷當(dāng)前是開(kāi)發(fā)環(huán)境和線(xiàn)上發(fā)布環(huán)境黔州,同時(shí)提供一個(gè)默認(rèn)的實(shí)現(xiàn)類(lèi)耍鬓,代碼如下:
public interface SerializationContext {
/**
* 線(xiàn)上發(fā)布環(huán)境下的默認(rèn)實(shí)現(xiàn)
*/
SerializationContext ALWAYS_RELEASE = new SerializationContext() {
@Override
public boolean isDebug() {
return false;
}
@Override
public boolean isRelease() {
return true;
}
};
/**
* 返回 true 表示當(dāng)前是開(kāi)發(fā)環(huán)境,某些序列化和反序列化操作會(huì)被執(zhí)行(例如調(diào)試信息的保存)
* @return
*/
boolean isDebug();
/**
* 返回 true 表示當(dāng)前是線(xiàn)上發(fā)布環(huán)境
* @return
*/
boolean isRelease();
}
可以看到流妻,isDebug 和 isRelease 本質(zhì)上是互斥的牲蜀,因此,更好的實(shí)現(xiàn)是保留一個(gè)即可绅这,沒(méi)必要在增加復(fù)雜度的情況下沒(méi)有得到其他任何好處涣达。當(dāng)然,隨著后面框架的迭代升級(jí)证薇,SerializationContext 可能會(huì)增加更多其他的環(huán)境上下文相關(guān)信息度苔。
讓我們回到 Serializer 類(lèi)的實(shí)現(xiàn)中,可以看到有兩個(gè)反序列化的方法浑度,deserialize 和 deserializeNotNull寇窑,后者是在前者執(zhí)行結(jié)果的基礎(chǔ)上增加對(duì)反序列化后對(duì)象是否為空的校驗(yàn),如果為空則拋出異常俺泣,使用者可以根據(jù)具體業(yè)務(wù)需求選用疗认,為空校驗(yàn)在 InternalSerialUtils.checkIsNotNull 方法中,代碼如下:
@NotNull
@Contract("null -> fail")
public static <T> T checkIsNotNull(@Nullable T value) {
if (!(value != null)) {
throw new AssertionError("Assertion failed.");
}
return value;
}
可以看到代碼中使用雙重否定來(lái)判斷 value 是否為空伏钠,這段代碼同樣顯得畫(huà)蛇添足横漏,直接判斷 value == null 即可。