静态内部类的序列化

14

在Java中,我们可以序列化静态内部类吗?这里的类本身被声明为静态。


13
当你尝试时会发生什么? - Brian Roach
1
我的应用程序在我这样做时运行良好。但是,为了实现这一点,我正在序列化内部和外部类,这对我来说并不必要,但我知道如果内部类被序列化,则外部类必须被序列化。此外,我对静态类是否可以序列化存在一些疑问。 - Tinkerbel
外部类与序列化_static_内部类无关。 - Ted Hopp
2
“静态内部类”是一个自相矛盾的说法。嵌套类只能是“静态的”或者“内部的”。 - user207421
3个回答

25
一个静态内部类在这方面与顶层类没有区别:如果它声明实现了Serializable(或是一个声明实现了Serializable的类的子类),则它可以被序列化。同样,和顶层类一样,在运行时进行序列化时遇到的所有对象都必须是可序列化的,以避免出现NotSerializableException异常。由于这个内部类是static的,外围类的特性对此无关紧要。

1
谢谢大家。我从你们这些人那里得到了我需要的东西。 - Tinkerbel

2

@Tinkerbel 需要注意的是 -

序列化静态嵌套类是没有问题的,但是如果在将来静态内部类被移到另一个外部类中,则反序列化旧对象会遇到问题。

所有字段都将被分配为默认/空值。


如果有人能解释一下为什么会这样就好了,我观察到了,但是没有一个非常令人信服的理由...听起来好像每当一个包被更改时,这种情况应该发生。 - user2674407

-2

看起来答案可能因为Java版本的不同而有所不同。

JDK 7中的序列化规范表示:

注意 - 强烈不建议对内部类进行序列化(即非静态成员类的嵌套类),包括局部类和匿名类,原因有几个。由于在非静态上下文中声明的内部类包含对封闭类实例的隐式非瞬态引用,因此序列化这样的内部类实例将导致其关联的外部类实例也被序列化。javac(或其他JavaTM编译器)为实现内部类生成的合成字段是与实现相关的,可能在编译器之间有所不同;这些字段的差异可能会破坏兼容性,并导致冲突的默认serialVersionUID值。分配给局部类和匿名内部类的名称也是与实现相关的,可能在编译器之间有所不同。由于内部类不能声明除了编译时常量字段之外的静态成员,它们无法使用serialPersistentFields机制来指定可序列化的字段。最后,与外部实例关联的内部类没有零参数构造函数(此类内部类的构造函数隐式接受封闭实例作为前置参数),因此它们无法实现Externalizable。然而,上述列出的问题都不适用于静态成员类。

通过在Oracle和IBM JDK 1.7版本之间序列化对象的经验来看,我可以告诉你它并不总是有效。我不能确定它总是失败,但你肯定不能指望它能正常工作。

我的应用程序中不会出现故障的代码路径,在 JDK 1.5 上生产了 5 年,并且我在之前的序列化文档中也没有看到与当前语句相似的内容。所以,似乎 Java 神已经允许在 JDK 7 中使用此代码模式。


5
这与问题不相关,问题明确指定了静态内部类。 - gerardw

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