簡體   English   中英

java ObjectOutputStream 方法的 defaultWriteObject 和 writeObject 的異同

[英]differences and similarities between defaultWriteObject and writeObject of java ObjectOutputStream methods

我正在嘗試了解java序列化機制,我幾乎沒有懷疑

請回答以下有關java序列化的問題:

  • 為什么我們使用oos.defaultWriteObject(); ? 根據這篇文章,它的存在是為了向后兼容。 而且我不太明白它是如何實現的。序列化的不兼容更改之一是刪除較新版本中的字段。 這意味着舊版本將不得不設置有時對用戶無效的默認值。這與添加新字段並允許設置默認值的新版本有何不同?
  • 在自定義序列化期間,使用oos.defaultWriteObject();是否有任何區別oos.defaultWriteObject(); oos.writeObject(address); 兩者不做同樣的事情嗎? 我的意思是將所有超類和當前類的非瞬態非靜態字段寫入 OOS。

這里

private void writeObject(java.io.ObjectOutputStream stream)
        throws IOException {
    stream.writeObject(name);
    stream.writeInt(id);
    stream.writeObject(DOB);
}

private void readObject(java.io.ObjectInputStream stream)
        throws IOException, ClassNotFoundException {
    name = (String) stream.readObject();
    id = stream.readInt();
    DOB = (String) stream.readObject();
}

上面的代碼產生與下面的代碼相同的結果

private void writeObject(java.io.ObjectOutputStream stream)
            throws IOException {
        stream.defaultWriteObject();
    }

    private void readObject(java.io.ObjectInputStream stream)
            throws IOException, ClassNotFoundException {
         stream.defaultReadObject();
    }

什么時候使用這兩種方法,什么時候只使用 writeObject(employee); //員工是我的全部對象//

  1. 這是可能的重復問題列表,但沒有回答我的問題。
  2. 問題 1它說 * 如果在寫入可選數據(如果有)之前沒有調用一次 defaultWriteObject 或 writeFields,那么在 ObjectInputStream* 的情況下,實例反序列化的行為是未定義的,但我仍然可以在不使用 deafultwriteobject.right 的情況下調用 writeObject ?
  3. 問題 2這些答案說 defaultwriteobject 方法將一些額外的數據寫入流,並反射性地檢查要寫入的內容。 oos.writeobject(object obj) 不也反思檢查嗎?
  4. 最后,我可以通過覆蓋 writeObject 和 ReadObject 方法來控制我的序列化,那么 Externalizable 的意義何在?
  5. 如果提供串行 versionUID 不會引發異常,如果我反序列化一個對象,該對象缺少來自具有該字段的舊類的字段,那么如果我提供自己的 SerialverUID ,基本上所有不兼容的更改會發生什么? 是否有自己的串行版本 UID 不會為所有兼容的更改拋出流損壞的異常?

對於您的問題

  1. writeObject不是為了向后兼容。 readObject是。
  2. 他們是一樣的。 defaultWriteObject是幫助您快速編寫“可序列化”值。

向后兼容

考慮您的 bean 添加了一個新字段。

class Bean implements Serializable {
  int id;
  String name;
  String newValue = "123";
}

盡管您已提供newValue默認值,但 java 序列化將忽略它。 (因為它分配實例而不是new實例)

現在,如果您不使用readObject ,您將獲得newValue=null 所以你還需要在readObject進行初始化。

  private void readObject(ObjectInputStream stream) throws Exception {
    stream.defaultReadObject();
    this.newValue = "123";
  }

defaultWriteObject如何幫助您

考慮到您的 bean 幾乎是“可序列化的”,除了某些字段。

請參閱以下代碼。 BadThing不可Serializable或者它有一些您不想序列化的敏感數據。

class Bean implements Serializable {
  int id;
  String string;
  BadThing badThing;
}

要快速序列化它,您可以讓字段transient並編寫writeObject方法來處理它

  private void writeObject(ObjectOutputStream stream) throws Exception {
    stream.defaultWriteObject();
    stream.writeInt(badThing.id);
  }

  // Corresponding `readObject`

當然,您可以將defaultWriteObject替換為多個writeXXX 但是如果你有很多很多字段,寫代碼很累很無聊吧?

所以defaultWriteObject只是為了讓您免於編寫無聊的代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM