公共最终字段的序列化
我使用一个简单的结构来存储只读值(例如 C# 中没有 setter 的属性)。为了实现这一点,我使用 public Final int test=42;
。
由于某些原因,我想允许序列化此类。我正在使用这段代码:
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.writeInt(test);
}
private void readObject(ObjectInputStream ois) throws IOException {
test=ois.readInt();
}
最后一个不起作用,因为现场测试是最终的,我该如何解决这个问题?
I'm using a simple struct where I store readonly values (like properties with no setter in C#). To achieve this I'm using public final int test=42;
.
For some reasons I want to allow to serialize this class. I'm using this code:
private void writeObject(ObjectOutputStream oos) throws IOException {
oos.writeInt(test);
}
private void readObject(ObjectInputStream ois) throws IOException {
test=ois.readInt();
}
The last one does not work because the field test is final how can I solve this issue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
readObject
应始终以defaultReadObject
或readFields
开头;writeObject
与defaultWriteObject
或putFields
。defaultReadObject
将为您设置final
字段。如果您想使用
readFields
,那么要么删除final
,要么隐藏在临时字段中并实现readResolve
(请注意,原始对象仍将可供感兴趣的各方使用)。一般来说,您确实不想求助于sun.misc.Unsafe
之类的东西。(J2SE 5.0 中引入的新 Java 内存模型 (JMM)(并在 JDK 1.4 中实现)在优化 Final 字段的方式上提供了更多自由。在问题的示例代码中,该字段是使用编译初始化的-时间常数 表达式。因此我希望它被内联(未测试)。)
readObject
should always start withdefaultReadObject
orreadFields
;writeObject
withdefaultWriteObject
orputFields
.defaultReadObject
will set thefinal
field for you.If you want to use
readFields
, then either remove thefinal
, or stash in a temporary field and implementreadResolve
(note the original object will still be available to interested parties). Generally you really don't want to resort to the likes ofsun.misc.Unsafe
.(The new Java Memory Model (JMM) introduce in J2SE 5.0 (and implemented in JDK 1.4) gives more liberties in the way final field can be optimised. In the example code of the question, the field is initialised with a compile-time constant expression. As such I'd expect it to be inlined (not tested).)
您可以使用反射来修改
test
的值上面假设您的应用程序具有
SecurityManager
授予的使用反射的权限。如果不存在,SecurityManager
将抛出异常。You can use reflection to modify the value of
test
The above assumes that your application has the permissions given by the
SecurityManager
to use reflection. If it does not, theSecurityManager
will throw an exception.首先,可以将
public final
基元常量设为public static final
,并且不需要序列化,因为它始终具有相同的值。但是,假设您有一个由构造函数设置的字段可能会有所不同。
注意:如果您有的话,安全经理通常不会允许这样做。
firstly, a
public final
primitive constant can be madepublic static final
and doesn't need to be serialised because its always the same value.However, say you have a field which is set by a constructor can can be different.
Note: security managers often doesn't allow this if you have one.
此
final
字段的值对于每个对象都会改变,还是对于所有对象都相同?即它是在构造函数还是字段声明级别设置的?如果它保持不变,最简单的解决方案是将其设为静态并消除读取和写入“只读”值的额外开销。另外,您是否必须提供readObject
和writeObject
实现而不是依赖默认机制?Does the value of this
final
field change for each object or is it the same for all objects? i.e. is it set at the constructor or the field declaration level? If it stays the same, the simplest solution here would be to make itstatic
and do away with the extra overhead of reading and writing the "read-only" values. Also, is it mandatory for you to provide thereadObject
andwriteObject
implementations rather than relying on the default mechanism?