淺析Java序列化中的四個常見問題

來源:互聯網
上載者:User

        一、實現對象序列化的方法有哪些?

        Java序列化有兩種實現方法,一種在類定義的時候實現Serializable介面,另一種是實現Externalizable介面。實現了這兩種介面的類的對象便可以轉換成位元組流或從位元組流恢複,不需要在類中增加任何代碼。只有極少數情況下帶需要定製代碼儲存或恢複對象狀態。

        一般選擇使用Serializable介面實現序列化,因為該介面不需要實現任何方法;而Externalizable介面定義了writeExternal()和readExternal()方法,實現該介面的類必須要實現這兩種方法。

         二、如何自訂序列化和還原序列化過程?

        在對象序列化的過程中,如果涉及一些敏感資訊,例如銀行卡帳號、密碼等,則需要考慮到保密和如何防止在傳遞過程中泄露的問題。使用transient關鍵字可以保護這些屬性,但是這些屬性將不會參與序列化過程。此時,可以考慮顯示定製序列化和還原序列化的過程,在序列化時加入加密、在還原序列化時加入解密等操作,而不是使用預設的序列化方式。

        對象在序列化和還原序列化時,是調用內部的writeObject()和readObject()方法實現的。writeObject()和readObject()方法的定義如下:

private void writeObject(ObjectOutputStream out) throws IOExceptionprivate void readObject(ObjectInputStream in) throws IOException

        注意:為了防止在對象序列化過程中調用預設的writeObject()和readObject()方法,必須將這兩個方法設定為private.    

        如果顯示定製序列化和還原序列化過程,只需重寫上述兩個方法。如果需要在writeObject()方法中使用預設的序列化機制,只需要在writeObject()方法中調用out.defaultWriteObject()方法;同理,在readObject()方法使用預設的序列化機制時,只需在readObject()方法中調用in.defaultReadObject()方法。

        在自訂序列化和還原序列化的過程中,對於簡單類型的屬性,必須使用預設的writeInt(int intValue)、readInt(int intValue)等方法對簡單類型進行讀寫操作;而對於參考型別的屬性,可以在writeObject(ObjectOutputStream out)和readObject(ObjectInputStream in)中使用readObject()和writeObject()方法進行讀寫。

        另外,在檔案或者網路中讀取屬性時,讀取的順序必須與寫入的順序保持一致。

        三、在序列化類別中添加serialVersionUID屬性有什麼作用?

        serialVersionUID是一個私人的靜態final屬性,用於表明類之間不同版本的相容性,該屬性不是必須的。當一個類實現了java.io.Serializable介面,但是沒有顯示定義一個Long類型的serialVersionUID屬性,java序列化機制會根據編譯的class自動產生一個serialVersionUID作為該類的序列化版本ID號,只有同一次編譯產生的class才會產生相同的serialVersionUID。在還原序列化過程中,JVM會把傳來的位元組流中的serialVersionUID與本地類的serialVersionUID進行比較,如果相同就認為版本一致,可以進行還原序列化,否則就會出現序列化版本不一致的InvalidClassException異常。如果不希望通過編譯來強制劃分軟體版本,即實現序列化介面的類能夠相容以前版本,只需顯示地定義一個名為serialVersionUID、類型為Long的final屬性,即可保證相同的版本號碼,且在進行序列化和還原序列化時不會出現InvalidClassException異常。

        四、當序列化遭遇繼承時,如何正確處理對象序列化過程?

        在序列化過程中,如果父類實現了Serializable和Externalizable介面,則其所有子類都將自動實現序列化。

        但是,在實際開發中,這是不可取的。因為父類不能強制其所有子類都具有序列化的能力。

        如果父類沒有序列化,而子類卻實現了Serializable介面,那麼子類對象也不能序列化。否則,會拋出InvalidClassException異常。

        下面,提供一種可行的方法,供大家參考:

        第一、編寫一個能夠實現序列化的子類,首先將自身序列化。

        第二、為其父類提供一個無參的構造方法並序列化父類的屬性。

public abstract class AbsSuperClass {protected int superValue;/** * 父類無參的構造方法 */public AbsSuperClass() {}public AbsSuperClass(int superValue) {this.superValue = superValue;}public int getSuperValue() {return superValue;}public void setSuperValue(int superValue) {this.superValue = superValue;}@Overridepublic String toString() {return "superValue = " + superValue;}}/** * 定義子類並顯示定義序列化和還原序列化過程 * @author gsucbiao * * @date 2011-9-7 && 上午12:23:35 */public class SubClass extends AbsSuperClass implements Serializable {private static final long serialVersionUID = 1L;private int subValue;public SubClass(int superValue, int subValue) {super(superValue);this.subValue = subValue;}private void writeObject(ObjectOutputStream out) throws IOException {out.defaultWriteObject();out.writeInt(superValue);}private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {in.defaultReadObject();superValue = in.readInt();}@Overridepublic String toString() {return super.toString() + "subValue = " + subValue;}}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.