您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關Java自定義序列化行為的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
正常情況下,一個類實現java序列化很簡單,只需要implements Serializable接口即可,之后該類在跨jvm的傳輸過程中會遵照默認java序列化規則序列化和反序列化;不同jvm版本之間序列化方式稍有不同,但基本上都是兼容的。
在某些特殊情況下,可能需要自定義序列化和反序列化的行為,看下面例子:
Java代碼
class AbstractSerializeDemo { private int x, y; public void init(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } public void printXY() { System.out.println("x:" + x + ";y:" + y); } } public class SerializeDemo extends AbstractSerializeDemo implements Serializable { private int z; public SerializeDemo() { super.init(10, 50); z = 100; } public void printZ() { super.printXY(); System.out.println("z:" + z); } public static void main(String[] args) throws IOException, ClassNotFoundException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); SerializeDemo sd = new SerializeDemo(); sd.printZ(); out.writeObject(sd); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); SerializeDemo sd2 = (SerializeDemo) in.readObject(); sd2.printZ(); } }
這段程序表示了一個可序列化的類繼承自一個非序列化的有狀態超類,期望的結果是,子類序列化以后傳輸并反序列化回來,原先的值域包括超類的值域都保持不變。
但是輸出是:
Java代碼
x:10;y:50 z:100 x:0;y:0 z:100
結果和期望不符,子類的值域保留下來了,但是超類的值域丟失了,這對jvm來說是正常的,因為超類不可序列化;
為了解決這個問題,只能自定義序列化行為,具體做法是在SerializeDemo里加入以下代碼:
Java代碼
private void writeObject(ObjectOutputStream os) throws IOException { os.defaultWriteObject();//java對象序列化默認操作 os.writeInt(getX()); os.writeInt(getY()); } private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException { is.defaultReadObject();//java對象反序列化默認操作 int x=is.readInt(); int y=is.readInt(); super.init(x,y); }
writeObject和readObject方法為JVM會在序列化和反序列化java對象時會分別調用的兩個方法,修飾符都是private,沒錯。
我們在序列化的默認動作之后將超類里的兩個值域x和y也寫入object流;與之對應在反序列化的默認操作之后讀入x和y兩個值,然后調用超類的初始化方法。
再次執行程序之后的輸出為:
Java代碼
x:10;y:50 z:100 x:10;y:50 z:100
另外還有兩個自定義序列化方法writeReplace和readResolve,分別用來在序列化之前替換序列化對象 和 在反序列化之后的對返回對象的處理。一般可以用來避免singleTon對象跨jvm序列化和反序列化時產生多個對象實例,事實上singleTon的對象一旦可序列化,它就不能保證singleTon了。JVM的Enum實現里就是重寫了readResolve方法,由JVM保證Enum的值都是singleTon的,所以建議多使用Enum代替使用writeReplace和readResolve方法。
Java代碼
private Object readResolve() { return INSTANCE; } private Object writeReplace(){ return INSTANCE; }
注:writeReplace調用在writeObject前;readResolve調用在readObject之后。
感謝各位的閱讀!關于“Java自定義序列化行為的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。