我们什么时候应该实现可序列化接口?为什么 Java 序列化存在缺陷该怎么办

2022-08-31 06:27:24
public class Contact implements Serializable {
    private String name;
    private String email;

    public String getName() {
        return name;
    }

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

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}
  1. 我应该何时实现接口?Serializable
  2. 我们为什么要这样做?
  3. 它是否具有任何优势或安全性?

答案 1
  1. 这个“序列化”的事情是什么?

    它允许您获取一个对象或一组对象,将它们放在磁盘上或通过有线或无线传输机制发送它们,然后,也许在另一台计算机上,反转该过程:复活原始对象。基本机制是将对象展平为一维位流,并将该位流转换回原始对象。

    就像《星际迷航》中的运输机一样,这一切都是关于把一些复杂的东西变成一个1和0的平面序列,然后把1和0的序列(可能在另一个地方,可能在另一个时间)重建原始复杂的“东西”。

    因此,当您需要存储对象的副本时,请实现该接口,将它们发送到在同一系统或网络上运行的另一个进程。Serializable

  2. 因为您要存储或发送对象。

  3. 它使存储和发送对象变得容易。它与安全性无关。


答案 2

这个问题的答案是,也许令人惊讶的是,从来没有,或者更现实地说,只有当你被迫与遗留代码进行互操作性时。这是Joshua Bloch在 Effective Java,3rd Edition 中的建议:

没有理由在您编写的任何新系统中使用 Java 序列化

Oracle的首席架构师Mark Reinhold公开表示,删除当前的Java序列化机制是一个长期目标。


为什么 Java 序列化存在缺陷

Java 作为语言的一部分,提供了一个序列化方案,您可以使用该接口选择加入。然而,这个方案有几个棘手的缺陷,Java语言设计师应该将其视为失败的实验。Serializable

  • 它从根本上假设人们可以谈论对象序列化形式。但是有无限多的序列化方案,导致无限多的序列化形式。通过强加一个方案,而没有任何改变方案的方法,应用程序不能使用最适合它们的方案。
  • 它是作为构造对象的附加方法实现的,它绕过构造函数或工厂方法执行的任何前提条件检查。除非编写了棘手、容易出错且难以测试的额外反序列化代码,否则您的代码可能具有巨大的安全漏洞。
  • 测试序列化表单的不同版本的互操作性非常困难。
  • 处理不可变对象很麻烦。

该怎么办

请改用可以显式控制的序列化方案。例如协议缓冲区、JSON、XML 或您自己的自定义方案。