程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 序列化Serializable和Externalizable的區別

序列化Serializable和Externalizable的區別

編輯:C++入門知識

序列化Serializable和Externalizable的區別


大家都知道Serializable是一個mark interface,告訴JVM這個對象可以被轉換成二進制流來傳輸.
但是Serializable與Externalizable的轉換二進制流的過程是不一樣的.
Serializable 在我們實現這個接口的時候,我們可以使用4個私有方法來控制序列化的過程:
我們來看一個例子:
Java代碼 收藏代碼
  1. public class FooImpl implements java.io.Serializable{
  2. private String message;
  3. public String getFoo() {
  4. return message;
  5. }
  6. public void setMessage(String message) {
  7. this.message = message;
  8. }
  9. private void writeObject(java.io.ObjectOutputStream out) throws IOException {
  10. System.out.println("writeObject invoked");
  11. out.writeObject(this.message == null ? "hohohahaha" : this.message);
  12. }
  13. private void readObject(java.io.ObjectInputStream in) throws IOException,
  14. ClassNotFoundException {
  15. System.out.println("readObject invoked");
  16. this.message = (String) in.readObject();
  17. System.out.println("got message:" + message);
  18. }
  19. private Object writeReplace() throws ObjectStreamException {
  20. System.out.println("writeReplace invoked");
  21. return this;
  22. }
  23. private Object readResolve() throws ObjectStreamException {
  24. System.out.println("readResolve invoked");
  25. return this;
  26. }
  27. public Object serialize() throws IOException, ClassNotFoundException {
  28. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  29. ObjectOutputStream oos = new ObjectOutputStream(baos);
  30. oos.writeObject(this);
  31. ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
  32. ObjectInputStream ois = new ObjectInputStream(bais);
  33. return ois.readObject();
  34. }
  35. public static void main(String[] args) throws IOException,
  36. ClassNotFoundException {
  37. FooImpl fooimpl = new FooImpl();
  38. fooimpl.serialize();
  39. }
    我們運行這段代碼看到的debug信息:
    writeReplace invoked
    writeObject invoked
    readObject invoked
    readResolve invoked


    當進行序列化的時候:
    首先JVM會先調用writeReplace方法,在這個階段,我們可以進行張冠李戴,將需要進行序列化的對象換成我們指定的對象.
    跟著JVM將調用writeObject方法,來將對象中的屬性一個個進行序列化,我們可以在這個方法中控制住哪些屬性需要序列化.

    當反序列化的時候:
    JVM會調用readObject方法,將我們剛剛在writeObject方法序列化好的屬性,反序列化回來.
    然後在readResolve方法中,我們也可以指定JVM返回我們特定的對象(不是剛剛序列化回來的對象).

    注意到在writeReplace和readResolve,我們可以嚴格控制singleton的對象,在同一個JVM中完完全全只有唯一的對象,控制不讓singleton對象產生副本.


    Externalizable 是一個有實際方法需要實現的interface,包括writeExternal和readExternal:
    Java代碼 收藏代碼
    1. public class FooImpl implements java.io.Externalizable {
    2. private String message;
    3. public String getFoo() {
    4. return message;
    5. }
    6. public void setMessage(String message) {
    7. this.message = message;
    8. }
    9. private Object writeReplace() throws ObjectStreamException {
    10. System.out.println("writeReplace invoked");
    11. return this;
    12. }
    13. private Object readResolve() throws ObjectStreamException {
    14. System.out.println("readResolve invoked");
    15. return this;
    16. }
    17. public Object serialize() throws IOException, ClassNotFoundException {
    18. ByteArrayOutputStream baos = new ByteArrayOutputStream();
    19. ObjectOutputStream oos = new ObjectOutputStream(baos);
    20. oos.writeObject(this);
    21. ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    22. ObjectInputStream ois = new ObjectInputStream(bais);
    23. return ois.readObject();
    24. }
    25. public void readExternal(ObjectInput arg0) throws IOException,
    26. ClassNotFoundException {
    27. System.out.println("readExternal invoked");
    28. Object obj = arg0.readObject();
    29. }
    30. public void writeExternal(ObjectOutput arg0) throws IOException {
    31. System.out.println("writeExternal invoked");
    32. arg0.writeObject("Hello world");
    33. }
    34. public static void main(String[] args) throws IOException,
    35. ClassNotFoundException {
    36. FooImpl fooimpl = new FooImpl();
    37. fooimpl.serialize();
    38. }
    39. }
      我們運行這段代碼看到的debug信息:
      writeReplace invoked
      writeExternal invoked
      readExternal invoked
      readResolve invoked
      在此writeExternal 和readExternal 的作用與writeObject和readObject 一樣.

      最後,當我們同時實現了兩個interface的時候,JVM只運行Externalizable 接口裡面的writeExternal 和readExternal 方法對序列化內容進行處理.
      需要注意的是:Serializable是一個真正的mark interface,
      writeObject,readObject, writeReplace,readResolve是直接與JVM通信,告訴JVM序列化的內容.

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved