“Serializable”接口背后的原理是什么?

3

如果我们想要对一个对象进行序列化,我们可以简单地实现以下内容:

class MyClass implements Serializable
{
  private static final long serialVersionUID = 12345L;
}

不需要额外的努力即可实现对象在文件中的读写,Java会自动处理一切。

另一方面,Externalizable定义了显式序列化和反序列化方法,因此我们可以进行编程式操作。

这让我想到一个问题:如果对于Serializable不需要额外的努力,为什么要将其作为接口来实现对象的序列化/反序列化,而不是默认情况下每个对象都可以进行序列化/反序列化呢?


好问题。在Python中,默认情况下,一切都可以被序列化或pickle-able。 - Martin Konecny
答案可以在这里找到:https://dev59.com/3XRC5IYBdhLWcg3wAcM3 - Martin Konecny
3个回答

4
当程序员将一个类标记为Serializable时,他要承担这样一个责任:如果这个类在未来发生了变化,那么保存了该类对象的程序仍然能够读取到更新后的类。更多细节请参见Effective Java Item 74: Implement Serializable judiciously。
还有另一个原因。你是否注意到ObjectOutput.writeObject(Object obj)接受的是Object,而不是Serializable?这是因为它假定对象可能使用不同的序列化机制进行保存。Serializable意味着对象应该使用Java标准序列化进行保存。

你是指 ObjectOutput.writeObject() 还是 ObjectOutputStream.writeObject() - user207421
我的意思是接口ObjectOutput,ObjectOutputStream.writeObject(Object)只接受可序列化的对象。 - Evgeniy Dorofeev

0
接口Serializable只是一个用于标识的掩码。如果每个类都具有可序列化的能力,则每个类都需要维护serialVersionUID以避免版本冲突。此外,它可能会引起安全问题:有人会将其用作创建新对象的方式,尽管该对象不打算由客户端代码创建。使用Serializable接口是不安全的。请参阅《Effective Java》获取更多信息。

0

因为:

  1. 并非所有对象都具有有意义的语义。例如:单例对象
  2. 安全性。如果您将对象传递给其他人的代码,并且他们始终可以捕获和传输对象,则安全相关代码需要有一个退出选项,当人们忽略对象时,会出现安全漏洞。因此,“默认关闭”更加安全。
  3. 内置序列化格式为您编写的每个对象编写类名,因此效率非常低。仅在数据很少的情况下使用它。
  4. 默认序列化不易与其他语言编写的代码共享数据,因此,如果今天编写的数据可能需要由将来的其他软件读取,则应考虑使用特定表示法。因此,它不是一个好的长期格式。
  5. 所有开发人员都不记得它在所有情况下的确切工作规则。

如果您阅读Joshua Bloch的书籍Effective Java,它会解释使用内置功能的棘手之处。大多数开发人员在许多情况下都会避免使用它。这个答案提供了一个很好的经验法则https://softwareengineering.stackexchange.com/a/240432/129659


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接