曾几何时,对于Java的序列化的认知一直停留在:「实现个Serializbale接口」不就好了的状态

序列化是干啥用的?

序列化的原本意图是希望对一个Java对象作一下“变换”,变成字节序列,这样一来方便持久化存储到磁盘,避免程序运行结束后对象就从内存里消失,另外变换成字节序列也更便于网络运输和传播,所以概念上很好理解:

  • 序列化:把Java对象转换为字节序列。
  • 反序列化:把字节序列恢复为原先的Java对象。

序列化 - 图1
而且序列化机制从某种意义上来说也弥补了平台化的一些差异,毕竟转换后的字节流可以在其他平台上进行反序列化来恢复对象。

对象如何序列化?

然而Java目前并没有一个关键字可以直接去定义一个所谓的“可持久化”对象。
对象的持久化和反持久化需要靠程序员在代码里手动显式地进行序列化和反序列化还原的动作。
举个例子,假如我们要对Student类对象序列化到一个名为student.txt的文本文件中,然后再通过文本文件反序列化成Student类对象:
序列化 - 图2
1、Student类定义

  1. public class Student implements Serializable {
  2. private String name;
  3. private Integer age;
  4. private Integer score;
  5. @Override
  6. public String toString() {
  7. return "Student:" + '\n' +
  8. "name = " + this.name + '\n' +
  9. "age = " + this.age + '\n' +
  10. "score = " + this.score + '\n'
  11. ;
  12. }
  13. // ... 其他省略 ...
  14. }

2、序列化

  1. public static void serialize( ) throws IOException {
  2. Student student = new Student();
  3. student.setName("CodeSheep");
  4. student.setAge( 18 );
  5. student.setScore( 1000 );
  6. ObjectOutputStream objectOutputStream =
  7. new ObjectOutputStream( new FileOutputStream( new File("student.txt") ) );
  8. objectOutputStream.writeObject( student );
  9. objectOutputStream.close();
  10. System.out.println("序列化成功!已经生成student.txt文件");
  11. System.out.println("==============================================");
  12. }

3、反序列化

  1. public static void deserialize( ) throws IOException, ClassNotFoundException {
  2. ObjectInputStream objectInputStream =
  3. new ObjectInputStream( new FileInputStream( new File("student.txt") ) );
  4. Student student = (Student) objectInputStream.readObject();
  5. objectInputStream.close();
  6. System.out.println("反序列化结果为:");
  7. System.out.println( student );
  8. }

4、运行结果
控制台打印:

  1. 序列化成功!已经生成student.txt文件
  2. ==============================================
  3. 反序列化结果为:
  4. Student:
  5. name = CodeSheep
  6. age = 18
  7. score = 1000

Serializable接口有何用?

上面在定义Student类时,实现了一个Serializable接口,然而当我们点进Serializable接口内部查看,发现它竟然是一个空接口,并没有包含任何方法!
image.png
试想,如果上面在定义Student类时忘了加implements Serializable时会发生什么呢?
实验结果是:此时的程序运行会报错,并抛出NotSerializableException异常:

我们按照错误提示,由源码一直跟到ObjectOutputStreamwriteObject0()方法底层一看,才恍然大悟:
image.png

https://zhuanlan.zhihu.com/p/72070210
https://segmentfault.com/a/1190000022799049