Java静态序列化规则?

44

我正在使用一些静态方法和字段来进行保存状态序列化。但我记得,序列化和静态可能会引起混乱。我是否应该将所有的静态变量都设为瞬态?如果反序列化调用inflate()函数,那么静态变量是否能够正常恢复?

7个回答

80

static是隐式的transient,因此您不需要将它们声明为这样。

序列化是用于序列化实例,而不是static字段(由于它们是类定义的一部分,因此方法并不重要,所以它们不会被序列化)将在加载类时重新初始化为其设置的任何值。

如果您有一个可变的static字段,则对该值进行的更改将丢失。


啊,我明白了,我不知道静态变量本质上是瞬态的。那么,我该如何确保重新实例化的对象仍然能够访问静态变量呢? - ahodder
静态变量存在于类加载时,因为它们是类定义的一部分。 - Robin
“静态变量默认是瞬态的”,这是否意味着有一种方法可以使它们不是瞬态的? - Steve Kuo
将“implicitly transient”这个词组改为“隐式瞬态”。如果您自定义序列化,可以有效地使它们变成非瞬态,但这不能“开箱即用”。 - Robin

10

以下是简短的规则:

1. 在序列化过程中,static变量不会被保存。反之,在反序列化过程中,static变量会从类级别初始化开始。

2. 带有statictransient关键字的变量在序列化时都会被忽略。

3. 类名和serialVersionUID都将作为字节流进行序列化,当反序列化时,从源头读取的serialVersionUID会与本地类的相同static变量进行比较。这就是为什么要将serialVersionUID声明为static public final,以便无需创建进一步的对象来比较这些版本UID。

  • 如果发现任何差异,则会出现一个InvalidClassException

3

static字段在序列化时会被忽略。

我更新了原始意图,将transient更正为static...


谢谢您的回复,我已经知道了。但是,当类从序列化过程中重新填充时,静态变量会返回吗? - ahodder
1
@Aedon:类的静态字段将继续保持在对象反序列化所在的虚拟机中已经设置的状态。如果在对象反序列化时首次初始化该类,则静态字段将处于其初始状态。 - ColinD
点赞了无意义的踩。答案完全正确。然而,楼主真正询问的是静态而不是瞬态。 - user207421
最初的负评是因为你实际上没有回答问题,而我没有发表评论,因为我认为这是显而易见的。无论如何,由于你的编辑,我已经取消了我的负评。 - Robin
谢谢。就我个人而言,我认为你的负评是恰当的,但是评论总是有用的,原因和代码审查一样有用:有时候你自己看不到自己尴尬的错误,直到有人向你展示它们为止 :-). - Brett Kail
显示剩余2条评论

1

static字段不会被序列化。


1
尽管静态字段serialVersionUID被序列化了,我知道这是一个相当旧的帖子,但我认为添加它应该是有益的 :) - Arunkumar Srisailapathi
@Arunkumar Srisailapathi,我来寻找你评论的同样事情背后的原因。你能帮忙解释一下这是如何工作的吗?按照规范,静态字段不会被序列化,serialVersionUID是否是一个例外? - Monish Kamble

1

静态属于类,序列化处理对象/实例。

因此,声明为静态后,它不再属于对象,无法进行序列化


0

非常简短但令人困惑的答案。静态变量不会被序列化。可序列化性与此无关。 “默认”在这里没有任何意义,第二个句子完全毫无意义。 - user207421
  1. 静态变量可序列化吗?是的或不是。
  2. 静态变量是否绑定到实例,特定对象?(据我们所知,它们绑定到类)...那么这里到底出了什么问题?是的或不是。
- Cris
@Cris 不,静态变量不会被序列化。我不明白你所说的以2开头的内容。 - user207421
好的...我现在真的没有时间做这个。我更新了我的评论到主问题,因为它不是很清楚。 - Cris
@Cris 仍然感到困惑。你的第一句话有点含糊不清。去掉“非静态”或“实例”中的一个,问题就解决了。 - user207421
显示剩余5条评论

0

静态字段永远不能成为“ser”文件的一部分。静态+瞬态与瞬态相同。


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