首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

深入理解 Java 對象序列化

     編輯:Java 相關知識

什麼是 Java 對象序列化?

Java 平台允許在內存中創建可復用的對象,但這些對象的生命週期通常不超過 JVM。現實應用中,往往需要在 JVM 停止後保存(持久化)指定對象,並在未來重新讀取。Java 對象序列化正是實現此功能的機制:保存對象時將其狀態轉為一組字節,未來再將字節組裝回對象。注意,序列化保存的是對象的「狀態」(即成員變量),不關注靜態變量。

除了持久化,RMI(遠程方法調用)或網絡傳輸對象時也會用到序列化。Java 序列化 API 提供了標準機制,簡單易用。

簡單示例

只要類實現 java.io.Serializable 接口即可被序列化。以下以 Person 類為例:

public enum Gender { MALE, FEMALE }

public class Person implements Serializable {
    private String name;
    private Integer age;
    private Gender gender;
    // 構造器、getter/setter、toString() 省略
}

序列化與反序列化程序:

public class SimpleSerial {
    public static void main(String[] args) throws Exception {
        File file = new File("person.out");
        ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream(file));
        Person person = new Person("John", 101, Gender.MALE);
        oout.writeObject(person);
        oout.close();

        ObjectInputStream oin = new ObjectInputStream(new FileInputStream(file));
        Object newPerson = oin.readObject();
        oin.close();
        System.out.println(newPerson);
    }
}

輸出:arg constructor [John, 31, MALE]。注意反序列化時未調用構造器,而是直接從字節還原對象。讀取時 CLASSPATH 必須包含 Person.class,否則拋出 ClassNotFoundException。

Serializable 的作用

ObjectOutputStream 在寫入對象時會檢查類型:若為 String、數組、Enum 或實現 Serializable 的對象,則進行序列化,否則拋出 NotSerializableException。

默認序列化機制

僅實現 Serializable 而無其他處理時,使用默認機制。序列化對象時會遞歸序列化其引用的所有對象,若對象圖複雜(如嵌套容器),開銷較大。

影響序列化的方法

1. transient 關鍵字

聲明為 transient 的字段會被默認序列化機制忽略。例如將 age 標記為 transient,反序列化後該字段為 null。

2. writeObject() 與 readObject() 方法

在類中私有定義這兩個方法可自定義序列化邏輯。例如對 transient 字段手動寫入/讀取:

private void writeObject(ObjectOutputStream out) throws IOException {
    out.defaultWriteObject();
    out.writeInt(age);
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    in.defaultReadObject();
    age = in.readInt();
}

這兩個方法均為 private,通過反射被調用。

3. Externalizable 接口

實現 Externalizable 後,基於 Serializable 的機制失效,序列化細節完全由程序員控制。必須實現 writeExternal 和 readExternal 方法,且類需提供公共無參構造器。反序列化時會先調用無參構造器創建對象,再填充字段。

4. readResolve() 方法

用於保護單例模式:反序列化時若返回單例實例,可確保單例唯一性。無論實現 Serializable 還是 Externalizable,讀取對象時都會調用 readResolve(),其返回對象會替換新創建的對象。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved