java序列化_Java序列化

java序列化

在我最近的一门课程中,我们讨论了Java 5注释。 我告诉我的学生,在那之前,人们不得不改用标记界面:一种没有任何方法的界面。 然后,我以Serializable接口为例。 我开始解释它,然后意识到我将需要很多时间来完全涵盖它。 这篇文章是对此的尝试。

序列化是将现有内存中Java对象转换为字节流的过程。 然后可以通过网络传输该流,或将其写入文件。

用例)

我没有证据来证明这一点,但是我相信序列化最初是为了将对象从一个正在运行的JVM实例转移到另一个。 例如,很久以前,EJB旨在跨越JVM边界。

虚拟机

为了使EJB从JVM迁移到另一个JVM,必须对其进行序列化。 因此,EJB的第一个版本必须是Serializable

情况不再如此。

我知道的唯一当前序列化用例是在Tomcat servlet / JSP容器中运行之间的会话数据存储:当Tomcat停止时,关闭挂钩将会话数据写入磁盘。 再次启动时,将从磁盘读取会话数据,以便用户在重新启动后仍可以访问其会话。 在这方面,该过程与WindowsHibernate功能非常相似。

该行为显然不是由API强制执行的,因为HttpSession.setAttribute()接受类型为Object的值。 但是,建议存储在会话中的对象实现可序列化以覆盖所有基础。

要求

如上所述, Serializable是标记接口:它没有方法。 但是,存在一些要求,即使它们与接口实现无关:

  • Serializable类的属性必须是:
    1. 原始类型
    2. Serializable类型
    3. 标记为transient ,因此不会序列化
  • Serializable类层次结构中的第一个不可序列Serializable必须提供一个无参数的构造函数。 将在反序列化过程中使用它。

自定义序列化

有时,一个对象有被序列化,但高于其类不能满足规则#2:一个属性是一个类型不的Serializable和显影剂的控制.eg以外InitialContext

为了克服该问题,Java允许通过3种方法来自定义序列化过程:

  • private void readObject(java.io.ObjectInputStream stream)
  • private void writeObject(java.io.ObjectOutputStream stream)
  • private void readObjectNoData()

尽管前两种方法很容易解释,但最后一种方法值得说明:

如果序列化流未将给定类列出为要反序列化的对象的超类,则readObjectNoData方法负责为其特定类初始化对象的状态。 在接收方使用与发送方不同的反序列化实例类的版本,并且接收方的版本扩展了发送方版本未扩展的类的情况下,可能会发生这种情况。 如果序列化流已被篡改,也会发生这种情况。 因此,尽管源流“敌对”或不完整,但readObjectNoData对于正确初始化反序列化的对象很有用。

— InputStream JavaDoc
https://docs.oracle.com/javase/9​​/docs/api/java/io/ObjectInputStream.html
根据设计,所有以前的方法都必须具有private修饰符。 这样做是为了防止在子类中覆盖它们。

可外部化

ExternalizableSerializable一种特殊化,它依赖于接口实现来自定义序列化。

可外部化
反序列化过程将检查Serializable是否也是Externalizable。 在后一种情况下,它将调用与外部相关的方法。 如果不是,它将默认为“默认”序列化。

类版本

另外,在上述Tomcat的会话序列的情况下,我提出一个隐含的假设:即Class的对象被序列化将是相同的Class的一个被反序列化。

尽管不常见,但并非总是如此。 例如,Tomcat已停止更新Webapp,并且该类已更新。 为了解决该问题,编译器在static final long serialVersionUID字段中写入一个版本。

允许使用任何访问修饰符,但应首选private

序列化过程将把serialVersionUID值与对象一起写入。 反序列化期间,该值将与当前在类路径中的类之一进行比较。 如果两者不同,则反序列化将失败,并显示InvalidClassException

无法保证保持不变的类会在整个编译器版本之间以及随着时间的推移生成serialVersionUID 。 因此,建议您自己编写该值-并仅在不兼容的类更改时更改它, 例如

  • 添加实例方法被认为是兼容的
  • 删除属性不是
有了这些信息,人们现在可能会理解为什么用IDE生成一个随机值会解决IDE警告,但完全没有用。

结论

很少需要Java序列化。 但是,当需要时,重要的是要知道它的优点。

翻译自: https://blog.frankel.ch/java-serialization/

java序列化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值