Java序列化对象与非序列化对象

3

1) 一个非序列化的Java对象能否被发送到网络上由另一个JVM执行或存储在本地文件中以恢复数据? 2) 序列化和存储Java对象与存储未序列化的Java对象有何区别?


将对象存储在文件或数据库中,或通过网络发送对象都意味着序列化。也许不是Java的ObjectOutputStream序列化方式,但某种形式的序列化(XML、JSON、ORM、Protobuf等)仍然需要进行。 - Thilo
谢谢Thio,更具体地说,只有实现Serializable接口的Java类才能通过网络发送吗? - Punter Vicky
4个回答

4

序列化是将 Java 对象表示为一系列字节的方法,它只是一种格式,仅此而已。

"内置"的 Java 序列化是一个类,提供了一个 API 来将 Java 对象转换为一系列字节。这就是全部。当然,反序列化是一种 "补充" 过程,允许将这个二进制流转换回对象。

序列化/反序列化本身与 "通过网络发送" 没有任何关系。只是方便地发送可以从对象使用序列化创建的二进制流。

更甚者,有时候内置的序列化不是获取二进制流的最佳方式,因为有时候可以使用更少的字节来转换对象。

因此,您可以使用自定义协议,为序列化提供自己的定制(例如 Externalizable),或者甚至使用第三方库,如 Apache Avro

我认为这有效地回答了你们的两个问题:

  1. 如果您想要将非序列化对象(我猜测是那些没有实现 "Serializable" 接口的对象)转换为字节流并通过网络发送,存储在二进制文件中等等,您可以自己完成。当然,您需要了解如何读取这种二进制格式以进行转换。

  2. 由于序列化只是一种转换协议而不是“与存储相关的事情”,答案是显而易见的。

希望这能有所帮助。


谢谢Mark - 说得非常清晰 :) 没有标记可序列化接口的对象如何存储在堆空间中?它们也是以二进制格式存储吗?这些对象能否被提取并原样发送到另一个jvm或状态,或者可以使用堆空间中对象的表示将其存储在DB中?在堆上的对象表示与标记为可序列化与不可序列化的对象有所区别吗?如果这些问题需要成为另一个主题的一部分,那我很抱歉。 - Punter Vicky
无论是否实现Serializable接口,使用'new'/反射创建的对象都存储在堆中。对象实现Serializable接口只是为了能够借助内置的序列化API(ObjectOutputStream)将其转换为字节流,并在以后执行反序列化。就这样。一旦您拥有一个表示为一系列字节的对象,您可以对这些字节做任何想做的事情-加载到数据库中,在文件系统中存储,在电子邮件中发送给您的朋友-任何事情。但这与序列化无关。这是网络编程-另一回事 :) - Mark Bramnik
谢谢马克!堆中存储的对象格式是什么?这个图像不能直接加载到另一个 JVM 的堆空间中并直接使用吗? - Punter Vicky
抱歉,我假设数据以字节的形式存储在堆中。我认为如果数据已经以字节的形式存储在堆中,为什么还需要特殊的指示器和过程来将其转换为字节。由于您提到Java对象只能通过反序列化创建,我假设Apache Avro和Externalizable在内部使用核心Java库提供的序列化API(ObjectOutputStream)来支持序列化/反序列化。我是正确的吗? - Punter Vicky
Externalizable 基本上与 Serializable 相同,但它提供了更细粒度的控制,可以决定什么应该被序列化以及如何序列化。我不太了解 Apache Avro 如何工作。 - Mark Bramnik
显示剩余2条评论

1
简而言之,在Java中你不能存储非序列化对象。因此,我会对两个问题都回答不。
编辑:如果您正在使用ObjectOutputStream和ObjectInputStream,它们可以写入原始类型以及可序列化对象。

谢谢Rogue。如果非序列化对象在网络上传输/存储在数据库中,Java会抛出异常吗?是什么阻止Java存储未实现“可序列化”接口的对象? - Punter Vicky
是的,在目标虚拟机中会收到NotSerializableException异常。防止不可序列化对象被序列化的原因是它没有序列化方法,因此不知道要写入什么内容。 - Rogue

1

1) 一个非序列化的Java对象能否通过网络发送到另一个JVM执行或存储在本地文件系统中以恢复数据?

使用ObjectOutputStream对对象进行编组,以便通过网络发送。序列化是一种Java标准方式,用于存储对象的状态。您可以自己设计做同样的事情,但除非您在标准方式中看到了大问题,否则没有重新发明轮子的必要。

2) 序列化和存储Java对象与存储未序列化Java对象之间有什么区别?

序列化使用ObjectOuputStream存储对象的状态,并可以使用ObjectInputStream进行反序列化。序列化的对象可以保存到文件中,也可以通过网络发送。序列化是实现所有这些的标准方式。但是,如果您真的有一个要点,您总是可以发明自己的方法来实现。


序列化是Java中存储对象状态的标准方式。对于长期持久性,它们似乎提供了第二种基于XML的格式。 - Thilo
@Thilo XML格式并非由Java定义,而是由W3C定义。Java当然通过诸如JAXB等框架支持对象到XML和XML到对象的转换。 - Juned Ahsan
XML格式不是由Java定义的,而是由W3C定义的。真的吗?java.beans.XMLEncoder在我的看法中似乎是JDK的一部分。 - Thilo
这就像说“Java语言是由Unicode联盟定义的”,仅仅因为我们在Java源代码中使用UTF-8一样。 - Thilo
@Thilo 并不完全准确,Java 提供符合不同规范的实现。在 Java 中有许多协议实现的 API 可用,并不意味着 Java 属于这些协议的联盟。 - Juned Ahsan

1
序列化的目的是以自包含的方式存储对象的状态,而不需要原始内存引用、运行时状态等。换句话说,对象可以表示为一串比特字符串,可以存储在磁盘上、通过网络发送等。

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