Java中序列化的目的是什么?

116

我已经阅读了很多关于串行化的文章,它被描述为非常好和伟大,但是没有一个论点能够令人信服。我想知道通过对类进行序列化我们到底能够实现什么?


8
他们回答他的问题时,他“并不信服”。 - Anthony Forloney
5
提供的回答事实上是正确的。如果对你没有用,可以将其作为评论回复并尝试解决问题,而不要忽视它们,当其他人指出你没有正确使用SO时再开始抨击别人。 - Anon.
4
Anon通过劝阻重复问题的出现,为该网站的质量做出了贡献。看到五个完全相同的问题是很傻的。如果你无法获得答案,有时候就是这样。如果你得到了答案,但似乎不起作用,那么可以在评论中继续讨论。SO并不是一个魔盒子,如果你仅仅问了正确的问题、问了足够多次或引起了正确专家的注意,它并不会像魔法一样自动给你一个答案。 - Chris
1
要么:(接受答案)要么:(发表评论和/或修改问题,解释为什么不是您需要的)。 - Anon.
1
似乎没有人指出你不序列化一个类,而是序列化代表类实例的对象。也许这有助于理解为什么它很有用? - Simon
显示剩余6条评论
9个回答

203

首先,让我们定义一下序列化,然后再谈为什么它非常有用。

序列化就是将现有对象转换为字节数组。这个字节数组表示对象的类别、版本和内部状态。然后可将此字节数组在运行相同代码的JVM之间用于传输/读取对象。

我们为什么要这样做呢?

有几个原因:

  • 通信:如果有两台运行相同代码的机器需要通信,一个简单的方法是一台机器构建一个包含要传输信息的对象,然后将该对象序列化到另一台机器。这不是最好的通信方法,但它能够完成工作。

  • 持久性:如果你想要将特定操作的状态存储在数据库中,可以将其轻松序列化成字节数组,并存储在数据库中以供以后检索。

  • 深度复制:如果你需要一个精确的对象副本,并且不想费力编写自己的专门clone()类,只需将对象序列化为字节数组,然后重新反序列化为另一个对象即可实现此目标。

  • 缓存:实际上只是上面的应用,但有时一个对象需要花费10分钟来构建,但只需要花费10秒钟来反序列化。因此,不要将巨型对象保存在内存中,而是通过序列化将其缓存到文件中,在以后需要时进行读取。

  • 跨JVM同步:序列化可以跨不同架构的不同JVM运行。


67
到底有什么东西可以在10分钟内建成? - oxbow_lakes
2
我的观点是(当然),序列化涉及的文件I/O可能会使任何纯对象创建开销相形见绌。我想你可能在谈论一些计算上非常昂贵的东西,比如科学建模,但由于难以处理模式更改,序列化是一种非常糟糕的持久化机制。 - oxbow_lakes
11
一个例子可能是,如果你维护一个特定数据集的索引以便快速搜索。这样的索引构建起来可能需要很长时间,但一旦构建完成,就可以相对较快地进行序列化和反序列化操作。 - David
如果Web应用程序请求必须在到达目的地之前通过全球每个路由器,构建对象,使用最长可能的路径返回对象,则可能需要10分钟。 - Vaibs
@Schmelter,既然您提到序列化不是最佳通信方法,那么应该实施哪种适当且最佳的方法呢? - Ashfaque Rifaye
据我所知,计算机内部的所有内容都由比特(因此也包括字节(8位比特序列))组成。如果是这样,那么它不是已经在内存(RAM)中用一个字节数组表示了吗?那么...把已经用字节表示的东西转换成字节数组有什么意义呢? - Sebastian Nielsen

72

当您运行应用程序时,它的所有对象都存储在内存(RAM)中。当您退出应用程序时,操作系统会回收该内存,并且您的程序基本上会“忘记”其运行过程中发生的一切。序列化通过让应用程序将对象保存到磁盘上来解决这个问题,以便下次启动应用程序时可以读取它们。如果您的应用程序要提供任何保存/共享之前状态的方式,则需要某种形式的序列化。


2
所以,看起来这只是一种更好、更有效的将数据写入文件并在需要时读取它的方式? - m_a_khan
1
这是唯一真正的解释。我想不出任何其他序列化+1的实际应用。 - Emily
简短明了,完美的解释。 - Yakhoob

21

我可以分享我的经历,希望它能够让你理解为什么序列化是必要的。但是,你问题的答案已经非常详细了。

我有几个项目需要加载并读取一堆文本文件。这些文件包含停用词、生物医学动词、生物医学缩写、语义相关联的单词等等。这些文件的内容很简单:单词

现在,对于每个项目,我需要从每个文件中读取单词并将它们放入不同的数组中;由于文件的内容从未改变,所以在第一个项目之后,这成为了一个常见但多余的任务。

因此,我的做法是创建一个对象来读取这些文件并填充各个数组(对象的实例变量)。然后,我对这些对象进行序列化,以便在以后的项目中,我只需进行反序列化即可,而不必再次读取文件和填充数组。


1
在这种情况下,为什么需要将它们存储在字节数组流中(使用序列化),难道不可以只使用临时字段更简单吗? - kidnan1991

5

Essentially:

序列化是将包含相互引用的一组对象实例转换为线性字节流的过程,然后可以通过套接字发送、存储到文件中或仅作为数据流进行操作。

维基百科查看用途:

序列化具有许多优点。它提供了以下功能:

  1. 比将对象属性写入磁盘上的文本文件并通过读取来重新组装更方便的对象持久化方法。
  2. 一个发出远程过程调用的方法,例如SOAP。
  3. 在组件化软件中(如COM,CORBA等)分发对象的方法。
  4. 检测时变数据变化的方法。

3
最显而易见的是,您可以通过网络传输序列化的类,并且接收方可以构造原始实例的副本。同样,您可以将序列化结构保存到文件系统中。
此外,请注意,序列化是递归的,因此如果需要,您可以一次性序列化整个异构数据结构。

0
序列化对象在空间中保持状态,它们可以通过网络、文件系统等传输……并且在时间上可以存活于创建它们的JVM之外。
有时这是很有用的。

这可以通过一个包含一些文本的简单文件实现。回读序列化对象要比读取写入到文本文件中的对象状态稍微容易一些,对吧? - m_a_khan
@m_a_khan:哇。是的,可以用简单的文本来完成。 但是一旦对象变得更加复杂,或者说它们的结构(组合、继承)变得更加复杂,手动(解)组合它们就会变得很麻烦。想象一下,如果对象成员是列表、集合和映射,那该怎么办。 - Dirk Schumacher
很容易想出不同的序列化方案,实际上有许多这样的方案存在。但出于非常好的原因,它们中没有一个在一般情况下会产生“简单文本”。 - David Soroko

0

我使用序列化对象来标准化传递给函数或类构造函数的参数。传递一个序列化的bean比长列表的参数更加简洁。结果是代码更易于阅读和调试。


1
在我看来,序列化和使用单个配置对象作为参数是相当独立的。也许这不是一个典型的用例。 - Gábor Bakos

0
在日常生活中,序列化被广泛应用的一个经典例子是电脑游戏中的“保存游戏”选项。当玩家决定保存游戏进度时,应用程序通过序列化将游戏的保存状态写入文件,当玩家“加载游戏”时,序列化文件被读取并重新创建游戏状态。

0

为了简单学习的目的(请注意,我说的是学习,而不是最好或者甚至好的,而只是为了理解问题),您可以将数据保存到计算机上的文本文件中,然后有一个程序读取该信息,并基于文件,您可以使程序有不同的反应。如果您已经更进一步,它不一定要是txt文件,而是其他类型的文件。

另一方面,序列化直接将事物转换成计算机语言。就像您用西班牙语告诉一台西班牙计算机某些东西,而不是告诉它一些法语,强制它学习法语,然后通过翻译把所有内容保存到本地的西班牙语中。这不是最技术密集型的答案,我只是试图用通俗易懂的语言格式创造一个易于理解的例子。

序列化也更快,因为在Java中,对象在堆上处理,比作为栈上的原始元素处理需要花费更长的时间。速度,速度,速度。从程序员的角度来看,减少了文件处理。


1
在试图用通俗易懂的语言来解释时,您并没有真正有用地解释序列化。 - user3516726

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