溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java自定義序列化行為的示例分析

發(fā)布時(shí)間:2021-12-03 17:51:56 來源:億速云 閱讀:184 作者:小新 欄目:編程語言

這篇文章給大家分享的是有關(guān)Java自定義序列化行為的示例分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。

正常情況下,一個(gè)類實(shí)現(xiàn)java序列化很簡單,只需要implements Serializable接口即可,之后該類在跨jvm的傳輸過程中會遵照默認(rèn)java序列化規(guī)則序列化和反序列化;不同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();         }     }

這段程序表示了一個(gè)可序列化的類繼承自一個(gè)非序列化的有狀態(tài)超類,期望的結(jié)果是,子類序列化以后傳輸并反序列化回來,原先的值域包括超類的值域都保持不變。

但是輸出是:

Java代碼

x:10;y:50    z:100    x:0;y:0    z:100

結(jié)果和期望不符,子類的值域保留下來了,但是超類的值域丟失了,這對jvm來說是正常的,因?yàn)槌惒豢尚蛄谢?

為了解決這個(gè)問題,只能自定義序列化行為,具體做法是在SerializeDemo里加入以下代碼:

Java代碼

private void writeObject(ObjectOutputStream os) throws IOException {           os.defaultWriteObject();//java對象序列化默認(rèn)操作           os.writeInt(getX());           os.writeInt(getY());       }           private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException {           is.defaultReadObject();//java對象反序列化默認(rèn)操作           int x=is.readInt();           int y=is.readInt();           super.init(x,y);       }

writeObject和readObject方法為JVM會在序列化和反序列化java對象時(shí)會分別調(diào)用的兩個(gè)方法,修飾符都是private,沒錯(cuò)。

我們在序列化的默認(rèn)動作之后將超類里的兩個(gè)值域x和y也寫入object流;與之對應(yīng)在反序列化的默認(rèn)操作之后讀入x和y兩個(gè)值,然后調(diào)用超類的初始化方法。

再次執(zhí)行程序之后的輸出為:

Java代碼

x:10;y:50    z:100    x:10;y:50    z:100

另外還有兩個(gè)自定義序列化方法writeReplace和readResolve,分別用來在序列化之前替換序列化對象 和 在反序列化之后的對返回對象的處理。一般可以用來避免singleTon對象跨jvm序列化和反序列化時(shí)產(chǎn)生多個(gè)對象實(shí)例,事實(shí)上singleTon的對象一旦可序列化,它就不能保證singleTon了。JVM的Enum實(shí)現(xiàn)里就是重寫了readResolve方法,由JVM保證Enum的值都是singleTon的,所以建議多使用Enum代替使用writeReplace和readResolve方法。

Java代碼

private Object readResolve()         {             return INSTANCE;         }                 private Object writeReplace(){             return INSTANCE;         }

注:writeReplace調(diào)用在writeObject前;readResolve調(diào)用在readObject之后。

感謝各位的閱讀!關(guān)于“Java自定義序列化行為的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學(xué)到更多知識,如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI