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

Java 序列化機制感性認識:Serializable 介面與 ObjectOutputStream 實戰

     編輯:J2SE

前言

Java 序列化設計極致簡單:實作 Serializable 標記介面,配合 ObjectOutputStream/ObjectInputStream 即可完成物件持久化與傳輸。本文透過完整範例建立直觀認識。

一、 核心機制

  • Serializable:標記介面,**無任何方法**,僅告知 JVM 該類別允許序列化。
  • ObjectOutputStream.writeObject():將物件圖寫入位元組流。
  • ObjectInputStream.readObject():從位元組流重建物件圖,回傳 Object 需強制轉型。
  • 自動處理:基本型別、字串、陣列、集合、物件引用圖 (含循環引用) 均自動處理。

二、 完整範例程式碼

package stream;

import java.io.*;

public class Serial implements Serializable {
    private int companyId;
    private String companyAddr;
    private boolean companyFlag;

    public Serial() {} // 無參建構子 (非必須,但建議保留)

    public Serial(int companyId, String companyAddr, boolean companyFlag) {
        this.companyId = companyId;
        this.companyAddr = companyAddr;
        this.companyFlag = companyFlag;
    }

    // 序列化實例方法
    public void serialize(ObjectOutputStream oout) throws IOException {
        oout.writeObject(this);
    }

    // 反序列化靜態工廠方法
    public static Serial deserialize(ObjectInputStream oin) 
            throws IOException, ClassNotFoundException {
        return (Serial) oin.readObject();
    }

    @Override
    public String toString() {
        return "DATA: " + companyId + " " + companyAddr + " " + companyFlag;
    }

    public static void main(String[] args) {
        Serial serial1 = new Serial(752, "dayer street #5 building 02-287", false);

        try (FileOutputStream out = new FileOutputStream("5.txt");
             ObjectOutputStream oout = new ObjectOutputStream(out);
             FileInputStream in = new FileInputStream("5.txt");
             ObjectInputStream oin = new ObjectInputStream(in)) {

            // 序列化
            serial1.serialize(oout);
            System.out.println("序列化完成");

            // 反序列化
            Serial serial2 = Serial.deserialize(oin);
            System.out.println("反序列化結果: " + serial2);

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

三、 執行結果

序列化完成
反序列化結果: DATA: 752 dayer street #5 building 02-287 false

四、 關鍵細節與最佳實踐

主題說明
serialVersionUID明確宣告 private static final long serialVersionUID = 1L; 避免類別變更導致反序列化失敗 (InvalidClassException)。
transient 關鍵字標記不需序列化的欄位 (如敏感資料、暫存計算結果、非序列化物件引用)。
自定義序列化實作 private void writeObject(ObjectOutputStream) 與 private void readObject(ObjectInputStream) 控制細節。
繼承與序列化父類別若未實作 Serializable,反序列化時會呼叫父類別無參建構子;若父類別已實作,則正常序列化父類別欄位。
安全性反序列化不可信資料極其危險 (RCE 風險),生產環境請使用 JEP 290 過濾器或改用 JSON/Protobuf 等安全格式。
效能與體積Java 原生序列化體積較大、速度較慢,高效能場景建議 Kryo, FST, Protobuf, Avro 等替代方案。

五、 總結

Java 序列化以「極簡 API」換取開發便利性,適合簡單持久化、RMI 傳輸、Session 複製等場景。理解其自動機制、版本控制與安全限制,是正確使用的前提。

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