【从零开始学Java | 第三十八篇】序列化流(Object Stream)

目录

前言

一、什么是序列化与反序列化

二、序列化流与反序列化流

1.序列化流的方法

2.反序列化流的方法

3.准备一个可序列化的类

4.序列化

5.反序列化

三、一些细节

1.对类添加一个属性

2.某个属性不想序列化到本地文件

总结


前言

在前面的 Java I/O 系列博客中,我们学会了如何使用字节流拷贝文件,也学会了如何使用字符流按行读取文本。

但是,在实际开发中,我们经常会遇到一种更高级的需求:我想把内存里活生生的 Java 对象(比如一个带有用户名、密码、等级的 User 对象)直接保存到硬盘上,或者通过网络发送给另一台电脑,该怎么做?

你当然可以自己把对象的属性拼接成字符串(比如 "张三,18,VIP")写进文件,读取时再自己切割字符串还原。但这种做法太低效也太容易出错了。Java 为此提供了一套终极解决方案:对象序列化流。

一、什么是序列化与反序列化

  • 序列化 (Serialization) :把内存中的 Java 对象转换成一串字节序列(二进制数据)的过程。

  • 反序列化 (Deserialization):把硬盘上或网络接收到的字节序列,重新恢复成内存中的 Java 对象的过程。

在 Java 中,完成这项魔法的两个核心处理流(包装流)是:

  • ObjectOutputStream:对象输出流(用于序列化写出)

  • ObjectInputStream:对象输入流(用于反序列化读取)

二、序列化流与反序列化流

1.序列化流的方法

构造方法 说明
public ObjectOutputStream(OutputStream out) 把基本流包装成高级流
成员方法 说明
public final void writeObject(Object obj) 将对象序列化写到文件

2.反序列化流的方法

| 构造方法 | 说明 |

public ObjectIutputStream(IutputStream out) 把基本流包装成高级流

| 成员方法 | 说明 |

public final void readObject(Object obj) 把序列化到本地文件中的对象,读取到程序中

3.准备一个可序列化的类

如果你想让一个类的对象支持序列化,这个类****必须实现 java.io.Serializable 接口。

我们可以看到Serializable接口是没有任何方法的,因此该接口只是一个标记型接口,用来标记一个类可以用来序列化的。

4.序列化

java 复制代码
public class Test {
    public static void main(String[] args) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("src\\c.txt"));

        Student s1 = new Student("zhangsan", 23);

        oos.writeObject(s1);

        oos.close();
    }
}

运行结果:

5.反序列化

java 复制代码
public class Test2 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("src\\c.txt"));

        Object o = ois.readObject();

        System.out.println(o);
        
        ois.close();

    }
}

运行结果:

三、一些细节

1.对类添加一个属性

当我们以旧类的形式以序列化形式写出到硬盘后,如果我们对类添加了一个新的属性值,之后再对之前写出的文件进行读入会有什么反应呢?

展示:

①我们首先对学生类在原有基础上添加了一个地址属性。

②读取旧属性序列化数据。

可以看到序列化使用了序列化版本值来标记类的,如果我们新添加了一个属性,这个版本值就会改变.

那么我们是不是可以把我们自己的类固定一个版本值,这样java在反序列化的时候就不会出现版本值不同的情况了呢?

此时读取时就不会出错了:

2.某个属性不想序列化到本地文件

有一些隐私属性,如果我不想序列化到本地文件应该怎么做?

我们可以对该属性添加一个"transient"关键字。

这样写出的数据就不会把地址值写到硬盘中,因此读入也不会将该属性读入。

总结

序列化流与反序列化流有三个很重要的细节:

  • 如果你想让一个类能够进行序列化写出,要让类实现 Serializable 接口
  • 版本号危机与 serialVersionUID
  • 使用 transient 保护敏感信息

🤗🤩

相关推荐
凤凰院凶涛QAQ8 小时前
《Java版数据结构 & 集合类剖析》Map & Set & 反射:“从哈希碰撞到红黑树转换,反射帮你扒开 HashMap 的桶数组看个究竟”
java·数据结构·算法
H.莓飛8 小时前
【数据结构】排序_OJ题(一):计数、桶与排序后的处理
java·开发语言·数据结构
wangchunyu1149 小时前
JAVA AQS与Lock实现原理(含CAS)
java·开发语言·word
爱喝水的鱼丶10 小时前
SAP-ABAP:ECC→S/4HANA ABAP 迁移升级指南——程序改造、语法兼容与性能优化 导语
运维·开发语言·性能优化·sap·abap·经验交流·开发交流
w_zero_one10 小时前
算法--模拟
java·数据结构·算法
小灰灰搞电子10 小时前
Rust+Slint 实现FTP客户端调试助手源码分享
开发语言·后端·rust
外收内放10 小时前
面向对象高级(实战案例)
开发语言·python·学习
Javatutouhouduan10 小时前
阿里1658页Java面试题总结(含答案)
java·高并发·java面试·java面试题·后端开发·java程序员·java八股文
秋天的怀念_David10 小时前
算法一千零一夜 · 第十三夜 幻方,武侠世界里的数学迷宫
java·程序人生·算法
专业程序开发源11 小时前
springboot欧缇蔓月子中心管理系统82697-计算机课程设计、毕业设计
java·spring boot·后端·python·spring·django·课程设计