Java 序列化:深入探索 Serializable 接口

在 Java 编程中,序列化是一个非常重要的概念,它允许我们将对象转换为字节流,以便于存储或传输。反序列化则是将字节流转换回对象的过程。尽管我们通常只需要让类实现 Serializable 接口即可实现序列化,但深入了解其背后的机制和细节,对于提升我们的编程技能和理解 Java 的内部工作原理非常有帮助。

1 理论基础

Java 序列化是在 JDK 1.1 中引入的特性,用于将 Java 对象转换为字节数组,便于存储或传输。反序列化则是将字节数组转换回 Java 对象的过程。

序列化的思想是“冻结”对象状态,然后写到磁盘或者在网络中传输;反序列化的思想是“解冻”对象状态,重新获得可用的 Java 对象。

要序列化的对象必须实现 Serializable 接口,否则会抛出 NotSerializableException 异常。

Serializable 接口定义

public interface Serializable {
   
}

Serializable 接口是一个空接口,没有任何方法。它的作用仅仅是作为一个标识,告诉 Java 虚拟机该类的对象是可以被序列化的。

2 实战演练

首先,我们创建一个简单的类 Wanger,包含两个字段 nameage,并实现 Serializable 接口。

class Wanger implements Serializable {
   
    private static final long serialVersionUID = -2095916884810199532L;

    private String name;
    private int age;

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public int getAge() {
   
        return age;
    }

    public void setAge(int age) {
   
        this.age = age;
    }

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

接下来,我们创建一个测试类,通过 ObjectOutputStreamWanger 对象序列化到文件中,再通过 ObjectInputStream 从文件中反序列化对象。

public class Test {
   
    public static void main(String[] args) {
   
        // 初始化
        Wanger wanger = new Wanger();
        wanger.setName("王二");
        wanger.setAge(18);
        System.out.println(wanger);

        // 把对象写到文件中
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("chenmo"));) {
   
            oos.writeObject(wanger);
        } catch (IOException e) {
   
            e.printStackTrace();
        }

        // 从文件中读出对象
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("chenmo")));) {
   
            Wanger wanger1 = (Wanger) ois.readObject();
            System.out.println(wanger1);
        } catch (IOException | ClassNotFoundException e) {
   
            e.printStackTrace();
        }
    }
}

3 序列化与反序列化的内部机制

ObjectOutputStream 在序列化对象时,会依次调用 writeObject()writeObject0()writeOrdinaryObject()writeSerialData()invokeWriteObject()defaultWriteFields()

ObjectInputStream 在反序列化对象时,会依次调用 readObject()readObject0()readOrdinaryObject()readSerialData()defaultReadFields()

3.1 defaultWriteFields() 方法

private void defaultWriteFields(Object obj, ObjectStreamClass desc) throws IOException {
   
    // 获取对象的类,并检查是否可以进行默认的序列化
    Class<?> cl = desc.forClass();
    desc.checkDefaultSerialize();

    // 获取对象的基本类型字段的数量,以及这些字段的值
    int primDataSize = desc.getPrimDataSize();
    desc.getPrimFieldValues(obj, primVals);
    // 将基本类型字段的值写入输出流
    bout.write(primVals, 0, primDataSize, false);

    // 获取对象的非基本类型字段的值
    ObjectStreamField[] fields = desc.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值