靜态變量序列化不會被儲存


最後的輸出是 10
父類的序列化與 Transient 關鍵字
一個子類實作了 Serializable 接口,它的父類都沒有實作 Serializable 接口,序列化該子類對象,然後反序列化後輸出父類定義的某變量的數值,該變量數值與序列化時的數值不同。
要想将父類對象也序列化,就需要讓父類也實作Serializable 接口。如果父類不實作的話的,就 需要有預設的無參的構造函數。如果你考慮到這種序列化的情況,在父類無參構造函數中對變量進行初始化,否則的話,父類變量值都是預設聲明的值,如 int 型的預設是 0,string 型的預設是 null。
我們熟悉使用 Transient 關鍵字可以使得字段不被序列化,那麼還有别的方法嗎?根據父類對象序列化的規則,我們可以将不需要被序列化的字段抽取出來放到父類中,子類實作 Serializable 接口,父類不實作,根據父類序列化規則,父類的字段資料将不被序列化。
序列化存儲規則


對同一對象兩次寫入檔案,列印出寫入一次對象後的存儲大小和寫入兩次後的存儲大小,然後從檔案中反序列化出兩個對象,比較這兩個對象是否為同一對象。一般的思維是,兩次寫入對象,檔案大小會變為兩倍的大小,反序列化時,由于從檔案讀取,生成了兩個對象,判斷相等時應該是輸入 false 才對,但是。。。
我們看到,第二次寫入對象時檔案隻增加了 5 位元組,并且兩個對象是相等的。。Java 序列化機制為了節省磁盤空間,具有特定的存儲規則,當寫入檔案的為同一對象時,并不會再将對象的内容進行存儲,而隻是再次存儲一份引用,上面增加的 5 位元組的存儲空間就是新增引用和一些控制資訊的空間。反序列化時,恢複引用關系,使得代碼中的 t1 和 t2 指向唯一的對象,二者相等,輸出 true。該存儲規則極大的節省了存儲空間。


報錯的語句即為config = in.readParcelable(null);
分析
根據android文檔介紹:
readParcelable (ClassLoader loader)
loader A ClassLoader from which to instantiate the Parcelable object, or null for the default class loader.即loader為空時系統會采取預設的class loader。
Android有兩種不同的classloaders:framework classloader和apk classloader,其中framework classloader知道怎麼加載android classes,apk classloader知道怎麼加載you code,apk classloader繼承自framework classloader,是以也知道怎麼加載android classes。
在應用剛啟動時,預設class loader是apk classloader,但在系統記憶體不足應用被系統回收會再次啟動,這個預設class loader會變為framework classloader了,是以對于自己的類會報ClassNotFoundException。
解決
将config = in.readParcelable(null);改為config = in.readParcelable(Config.class.getClassLoader());
Config.class.getClassLoader()即為apk classloader, 其中Config.class可以改為你程式中自己寫的任意類,因為他們同樣指向apk loader。
試着改為config = in.readParcelable(Activity.class.getClassLoader());你會發現依然ClassNotFoundException因為Activity.class.getClassLoader()指向的是framework classloader
本文轉自我愛物聯網部落格園部落格,原文連結:http://www.cnblogs.com/yydcdut/p/4470190.html,如需轉載請自行聯系原作者