序列化和不可变对象
我有一个用于不可变使用的类,因此我想将所有字段标记为final
。
然而,该类被序列化和反序列化以通过网络发送。为此,需要一个空的构造函数。这阻止我创建最终字段。
我确信这是一个相当常见的问题,但我找不到解决方案。我应该如何进行?
I have a class which is intended for immutable use, hence I would like to label all the fields final
.
However the class is serialized and deserialized to send over the network. For this to work an empty constructor is required. This prevents me creating the final fields.
I'm sure this is a fairly common problem but I can't find a solution. How should I proceed?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
不需要无参数构造函数。最派生的不可序列化类确实需要一个可供最不派生的可序列化类使用的无参数构造函数。
如果您需要更改
readObject
内的字段,请通过readResolve
和writeReplace
使用串行代理。A no-arg constructor is not required. The most derived non-serialisable class does need a no-arg constructor available to the least-most derived serialisable class.
If you need to mutate fields inside a
readObject
, then use a serial proxy throughreadResolve
andwriteReplace
.在典型的序列化情况下,类不需要具有空构造函数或可序列化的非最终字段。
现在,如果您必须执行自己的序列化,或者您需要子类化未实现可序列化的类,那就是另一回事了。
因此,您需要提供更多有关您遇到问题的详细信息。
In the typical serialization case, it is not required that class have an empty constructor or non-final fields to be serializable.
Now, if you have to do your own serialization, or you need to subclass a class that doesn't implement Serializable, that is a different story.
So you need to provide some more details of how you are having a problem.
此问题是 Java 语言的未解决错误。 (请注意,这只适用于必须手动执行序列化的情况,例如使用 readObject)
This issue is an open bug on the Java language. (Note that this only applies if you have to do the serialization manually, such as with readObject)
与前面所说的相呼应,如果您采用实现
java.io.Serialized
接口的方法,则不需要无参数构造函数。例如,看一下 java.lang.Integer 源代码,一个简单的可序列化/不可变类,它有两个构造函数:一个接受 int,另一个接受 String。源代码: http://www.docjar.com/html /api/java/lang/Integer.java.html。 Javadoc: http://java.sun.com/ javase/6/docs/api/java/lang/Integer.html。另外,根据类的复杂性和您正在执行的操作,您可以考虑通过 java.io.Externalizable 接口实现序列化(尽管有些人认为它已经过时,并且它确实需要无参数构造函数)。以下是 SO 的概述: Serialized 和 Serialized 有什么区别和 Java 中的可外部化?,这是官方 Java 教程:http://java.sun.com/docs/books/tutorial/javabeans/persistence/index.html。
To echo what has been said, no-arg constructors are not a requirement if you are taking the route of implementing the
java.io.Serializable
interface. Take a look at thejava.lang.Integer
source code for example, a simple serializable/immutable class that has two constructors: one that takes an int, and one that takes a String. Source code: http://www.docjar.com/html/api/java/lang/Integer.java.html. Javadoc: http://java.sun.com/javase/6/docs/api/java/lang/Integer.html.Also depending on the complexity of your class and what you are doing, you could consider implementing serialization via the
java.io.Externalizable
interface (although some consider it outdated, and it DOES require a no-arg constructor). Here's an overview on SO: What is the difference between Serializable and Externalizable in Java?, and here's the official Java tutorial: http://java.sun.com/docs/books/tutorial/javabeans/persistence/index.html.作为记录,因为我有类似的问题:
我收到一条消息“java.io.InvalidClassException:com.example.stuff.FooBar; com.example.stuff.FooBar;没有有效的构造函数”
我认为这是因为它缺少默认构造函数。但上面的答案证实它不是强制性的(但是我们的应用程序使用了一个旧的序列化器,它确实需要一个默认的构造函数,因此可能会出现这种情况)。
然后我找到了一个页面,上面写着:
我想这就是我收到的消息。看起来核心问题是经典的:我将一个类声明为可序列化,但超类不是!我将可序列化接口在层次结构中向上移动,一切都很好。
但这个消息有点误导......:-)
For the record, since I had a similar issue:
I had a message "java.io.InvalidClassException: com.example.stuff.FooBar; com.example.stuff.FooBar; no valid constructor"
I thought it was because it was lacking a default constructor. But the above answers confirm it is not mandatory (but our app. uses an old serializer that indeed require a default constructor, so the case can arise).
Then I found a page stating:
Hence the message I got, I suppose. It appeared that the core issue was classical: I declared a class as serializable, but the superclass was not! I moved the Serializable interface up in the hierarchy, and all was well.
But the message was a bit misleading... :-)
不需要无参数构造函数。让我们阅读源代码:
因此,实际上类型层次结构中最近的非
Serialized
类中需要无参数构造函数。这意味着下面的类
Domain
可以被序列化。但
Son
类不能:A no-arg constructor is not required. Let's read the source code:
So, actually the no-arg constructor is required in the nearest not
Serializable
class in the type hierarchy.It means the following class
Domain
can be serialized.But the class
Son
can't: