Java中的序列化与反序列化

Java中的序列化(Serialization)与反序列化(Deserialization)是用于将对象转换为字节流(或文本格式)以便存储或传输,以及将字节流恢复为对象的过程。以下是详细说明:


1. 核心概念

  • 序列化:将对象转换为字节流(或其他格式,如JSON、XML),使其可以保存到文件、数据库或通过网络传输。
  • 反序列化:将字节流(或文本格式)还原为内存中的对象。

2. 实现方式

Java原生支持序列化,主要通过以下接口和类实现:

  • Serializable 接口:标记接口(无方法),表示类可以被序列化。
  • ObjectOutputStream:将对象写入字节流。
  • ObjectInputStream:从字节流读取对象。
示例代码
import java.io.*;

// 实现 Serializable 接口
class Person implements Serializable {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{name='" + name + "', age=" + age + "}";
    }
}

public class SerializationDemo {
    public static void main(String[] args) {
        // 序列化
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.ser"))) {
            Person person = new Person("Alice", 30);
            oos.writeObject(person);
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 反序列化
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.ser"))) {
            Person restoredPerson = (Person) ois.readObject();
            System.out.println(restoredPerson); // 输出:Person{name='Alice', age=30}
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

3. 关键细节

3.1 transient 关键字
  • 标记字段不参与序列化(如敏感信息)。
private transient String password;
3.2 serialVersionUID
  • 显式声明序列化版本号,避免类结构变化导致反序列化失败。
private static final long serialVersionUID = 1L;
  • 如果类没有显式声明 serialVersionUID,Java会根据类的结构自动生成一个版本号。在反序列化时,如果对象新增一个字段,此时Java会检测到 serialVersionUID 不一致,抛出 InvalidClassException 异常。
3.3 自定义序列化
  • 通过重写 writeObject()readObject() 方法控制序列化过程。
private void writeObject(ObjectOutputStream out) throws IOException {
    // 自定义序列化逻辑
}

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    // 自定义反序列化逻辑
}
3.4 Externalizable 接口
  • 提供更精细的序列化控制(需实现 writeExternal()readExternal() 方法)。
  • Serializable 更高效,但需要手动处理字段。

4. 常见问题与注意事项

  1. 版本兼容性
    • 修改类结构(如增删字段)可能导致反序列化失败,显式声明 serialVersionUID 可缓解。
  2. 安全性
    • 反序列化可能执行恶意代码,需确保数据来源可信。
  3. 性能
    • Java原生序列化效率较低,对性能敏感的场景可考虑其他格式(如JSON、Protobuf)。
  4. 跨语言支持
    • Java原生序列化仅适用于Java,跨语言通信建议使用JSON、XML或二进制协议(如Avro、Thrift)。

5. 替代方案

  • JSON序列化:使用库如 JacksonGson
    // 使用 Jackson 示例
    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writeValueAsString(person);
    Person restoredPerson = mapper.readValue(json, Person.class);
    
  • XML序列化:使用 JAXB(Java Architecture for XML Binding)。
  • 二进制协议:如 Protocol BuffersApache Avro

6. 应用场景

  • 对象持久化(保存到文件或数据库)。
  • 远程方法调用(RPC,如Java RMI)。
  • 分布式缓存(如Redis存储对象)。
  • 网络通信(如HTTP接口传输JSON)。

总结

Java原生序列化简单易用,但需注意版本控制和安全性。在实际开发中,根据场景选择合适的方式(如JSON、Protobuf)能提升效率和跨语言兼容性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小九没绝活

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值