公共最终字段的序列化

发布于 2024-12-12 17:16:33 字数 389 浏览 0 评论 0原文

我使用一个简单的结构来存储只读值(例如 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

╰◇生如夏花灿烂 2024-12-19 17:16:33

readObject 应始终以 defaultReadObjectreadFields 开头; writeObjectdefaultWriteObjectputFieldsdefaultReadObject 将为您设置 final 字段。

如果您想使用 readFields,那么要么删除 final,要么隐藏在临时字段中并实现 readResolve(请注意,原始对象仍将可供感兴趣的各方使用)。一般来说,您确实不想求助于 sun.misc.Unsafe 之类的东西。

(J2SE 5.0 中引入的新 Java 内存模型 (JMM)(并在 JDK 1.4 中实现)在优化 Final 字段的方式上提供了更多自由。在问题的示例代码中,该字段是使用编译初始化的-时间常数 表达式。因此我希望它被内联(未测试)。)

readObject should always start with defaultReadObject or readFields; writeObject with defaultWriteObject or putFields. defaultReadObject will set the final field for you.

If you want to use readFields, then either remove the final, or stash in a temporary field and implement readResolve (note the original object will still be available to interested parties). Generally you really don't want to resort to the likes of sun.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).)

芯好空 2024-12-19 17:16:33

您可以使用反射来修改test的值

// Get the Class object for the class of which test is a field
Class<?> myClass = MyClass.class;

// We will need to set test as accessible so as to change it's value
// Get the Field object for test
Field testField = myClass.getDeclaredField("test");
// Save the current accessibility of test
boolean wasAccessible = testField.isAccessible();
// Mark test as accessible
testField.setAccessible(true);
// Set the value of test for this instance of MyClass
int newTestValue = 42;
testField.setInt(this, newTestValue);
// Restore the accesibility of test to it's original
testField.setAccessible(wasAccessible);

上面假设您的应用程序具有SecurityManager授予的使用反射的权限。如果不存在,SecurityManager 将抛出异常。

You can use reflection to modify the value of test

// Get the Class object for the class of which test is a field
Class<?> myClass = MyClass.class;

// We will need to set test as accessible so as to change it's value
// Get the Field object for test
Field testField = myClass.getDeclaredField("test");
// Save the current accessibility of test
boolean wasAccessible = testField.isAccessible();
// Mark test as accessible
testField.setAccessible(true);
// Set the value of test for this instance of MyClass
int newTestValue = 42;
testField.setInt(this, newTestValue);
// Restore the accesibility of test to it's original
testField.setAccessible(wasAccessible);

The above assumes that your application has the permissions given by the SecurityManager to use reflection. If it does not, the SecurityManager will throw an exception.

临风闻羌笛 2024-12-19 17:16:33

首先,可以将public final基元常量设为public static final,并且不需要序列化,因为它始终具有相同的值。

但是,假设您有一个由构造函数设置的字段可能会有所不同。

int test=ois.readInt();
Field testField = getClass().getDeclaredField("test");
testField.setAccessible(true);
testField.set(this, test);

注意:如果您有的话,安全经理通常不会允许这样做。

firstly, a public final primitive constant can be made public 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.

int test=ois.readInt();
Field testField = getClass().getDeclaredField("test");
testField.setAccessible(true);
testField.set(this, test);

Note: security managers often doesn't allow this if you have one.

往日情怀 2024-12-19 17:16:33

final 字段的值对于每个对象都会改变,还是对于所有对象都相同?即它是在构造函数还是字段声明级别设置的?如果它保持不变,最简单的解决方案是将其设为静态并消除读取和写入“只读”值的额外开销。另外,您是否必须提供 readObjectwriteObject 实现而不是依赖默认机制?

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 it static and do away with the extra overhead of reading and writing the "read-only" values. Also, is it mandatory for you to provide the readObject and writeObject implementations rather than relying on the default mechanism?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文