您好,登錄后才能下訂單哦!
本篇內容主要講解“使用Serializable的原因”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“使用Serializable的原因”吧!
經常看到有些類調用了Serializable接口,而有些類又沒有調用Serializable接口。那么什么情況下要調用Serializable接口。
首先來了解一下Serializable。(類通過實現 java.io.Serializable 接口以啟用其序列化功能。未實現此接口的類將無法使其任何狀態序列化或反序列化。序列化接口Serializable沒有方法或字段,僅用于標識可序列化的語義)
實現了Serializable接口的對象,可將它們轉換成一系列字節,并可在以后完全恢復回原來的樣子。這一過程亦可通過網絡進行。這意味著序列化機制能自動補償操作系統間的差異。換句話說,可以先在Windows機器上創建一個對象,對其序列化,然后通過網絡發給一臺Unix機器,然后在那里準確無誤地重新“裝配”。不必關心數據在不同機器上如何表示,也不必關心字節的順序或者其他任何細節。
serialization主要用來支持2種主要的特性:
1、RMI(Remote method invocation)。
RMI允許象在本機上一樣操作遠程機器上的對象。當發送消息給遠程對象和調用遠程方法時,就需要用到serializaiton機制來發送參數和接收返回值。
2、保存信息。
在某個時候把狀態信息保存起來,以便以后某個時候能恢復這些狀態信息。
Hibernaet和EJB中的實體Bean就用到了上面兩個特性。
另外:保存的時候不僅能保存對象的副本,而且還會把對象里面所引用的對象也保存起來,以此類推。就像在編譯某個類一樣,會涉及到所用到的所有類。但是所引用的對象也必須是可序列化的,不然會拋NotSerializableException異常。
下面來寫個例子:(A和B類都是可序列化的,WriteObj:將A序列化,ReadObj:將A反序列化)
class A:
package woxingwosu; import java.io.Serializable; public class A implements Serializable{ private String name="my name is a"; private B b=null; A(){ b=new B(); } public B getB() { return b; } public void setB(B b) { this.b = b; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String show(){ return "a.toString <a.name=\""+this.name+"\" a.b.name=\""+this.b.getName()+"\">" +"\na="+this.toString()+" b="+this.b.toString(); } }
class B:
package woxingwosu; import java.io.Serializable; public class B implements Serializable{ private String name="my name is B"; B(){} public String getName() { return name; } public void setName(String name) { this.name = name; } }
class WriteSeri:
package woxingwosu; import java.io.FileOutputStream; import java.io.ObjectOutputStream; /** * 寫Object(系列化) * @author 我行我素 */ public class WriteSeri { public static void main(String[] args) { ObjectOutputStream outObj=null; try{ FileOutputStream outStr=new FileOutputStream("obj.txt"); outObj=new ObjectOutputStream(outStr); A a=new A(); outObj.writeObject(a); System.out.println("write obj :"+a.show()); outObj.flush(); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(outObj!=null) outObj.close(); }catch(Exception e){ e.printStackTrace(); } } }}
class ReadSeri:
package woxingwosu; import java.io.FileInputStream; import java.io.ObjectInputStream; /** * 讀Object(反系列化) * @author 我行我素 */ public class ReadSeri { public static void main(String[] args) { ObjectInputStream inObj=null; try{ FileInputStream inStr=new FileInputStream("obj.txt"); inObj=new ObjectInputStream(inStr); A a=(A)inObj.readObject(); System.out.println("read Object :"+a.show()); }catch(Exception e){ e.printStackTrace(); }finally{ try{ if(inObj!=null) inObj.close(); }catch(Exception e){ e.printStackTrace(); } } } }
首先,我們運行WriteObj,實現序列化,得到輸出結果
write obj :a.toString <a.name="my name is a" a.b.name="my name is B"> a=woxingwosu.A@a90653 b=woxingwosu.B@de6ced
然后我們再運行ReadObj,實現反序列化,得到輸出結果
read Object :a.toString <a.namea.name="my name is a" a.b.name="my name is B"> a=woxingwosu.A@a90653 b=woxingwosu.B@de6ced
遺漏了一個問題,就是標識版本的serialVersionUID。
官方文檔:如果可序列化類未顯式聲明 serialVersionUID,則序列化運行時將基于該類的各個方面計算該類的默認 serialVersionUID 值,如“Java(TM) 對象序列化規范”中所述。不過,強烈建議 所有可序列化類都顯式聲明 serialVersionUID 值,原因計算默認的 serialVersionUID 對類的詳細信息具有較高的敏感性,根據編譯器實現的不同可能千差萬別,這樣在反序列化過程中可能會導致意外的 InvalidClassException。因此,為保證 serialVersionUID 值跨不同 java 編譯器實現的一致性,序列化類必須聲明一個明確的 serialVersionUID 值。還強烈建議使用 private 修改器顯示聲明 serialVersionUID(如果可能),原因是這種聲明僅應用于立即聲明類 -- serialVersionUID 字段作為繼承成員沒有用處。
剛才寫的例子中就沒有用到serialVersionUID,這時JVM會根據類名、接口名、成員方法及屬性等來生成一個64位的哈希字段作為serialVersionUID。但是如果序列化和反序列化的JVM版本不一樣的話,還是顯示寫上serialVersionUID安全。
到此,相信大家對“使用Serializable的原因”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。