最终瞬态场和序列化 [英] final transient fields and serialization
问题描述
在Java中进行序列化后,是否可以将最终瞬态
字段设置为任何非默认值?我的用例是缓存变量 - 这就是 transient
的原因。我也养成了 Map
字段的习惯,这些字段不会被更改(即地图内容已更改,但对象本身保持不变)最终
。但是,这些属性似乎是矛盾的 - 虽然编译器允许这样的组合,但是在反序列化后我不能将字段设置为 null
。
Is it possible to have final transient
fields that are set to any non-default value after serialization in Java? My usecase is a cache variable — that's why it is transient
. I also have a habit of making Map
fields that won't be changed (i.e. contents of the map is changed, but object itself remains the same) final
. However, these attributes seem to be contradictory — while compiler allows such a combination, I cannot have the field set to anything but null
after unserialization.
我尝试了以下内容,但未成功:
I tried the following, without success:
- 简单字段初始化(如示例所示):这是什么我通常这样做,但是在反序列化后似乎没有进行初始化;
- 构造函数中的初始化(我相信这在语义上和上面相同);
- 指定
readObject()
中的字段 - 由于该字段为final
,因此无法完成。
- simple field initialization (shown in the example): this is what I normally do, but the initialization doesn't seem to happen after unserialization;
- initialization in constructor (I believe this is semantically the same as above though);
- assigning the field in
readObject()
— cannot be done since the field isfinal
.
在示例中缓存
是 public
仅用于测试。
In the example cache
is public
only for testing.
import java.io.*;
import java.util.*;
public class test
{
public static void main (String[] args) throws Exception
{
X x = new X ();
System.out.println (x + " " + x.cache);
ByteArrayOutputStream buffer = new ByteArrayOutputStream ();
new ObjectOutputStream (buffer).writeObject (x);
x = (X) new ObjectInputStream (new ByteArrayInputStream (buffer.toByteArray ())).readObject ();
System.out.println (x + " " + x.cache);
}
public static class X implements Serializable
{
public final transient Map <Object, Object> cache = new HashMap <Object, Object> ();
}
}
输出:
test$X@1a46e30 {}
test$X@190d11 null
推荐答案
不幸的是,简短的回答是不 - 我经常想要这个。但瞬态不可能是最终的。
The short answer is "no" unfortunately - I've often wanted this. but transients cannot be final.
最终字段必须通过直接赋值初始值或在构造函数中初始化。在反序列化期间,这些都不会被调用,因此必须在反序列化期间调用的'readObject()'私有方法中设置瞬态的初始值。为了实现这一目标,瞬态必须是非最终的。
A final field must be initialized either by direct assignment of an initial value or in the constructor. During deserialization, neither of these are invoked, so initial values for transients must be set in the 'readObject()' private method that's invoked during deserialization. And for that to work, the transients must be non-final.
(严格来说,决赛只是在他们第一次阅读时才是最终的,所以有一些黑客攻击可能会在读取之前分配一个值,但对我来说这是一个太过分了。)
(Strictly speaking, finals are only final the first time they are read, so there are hacks that are possible that assign a value before it is read, but for me this is going one step too far.)
这篇关于最终瞬态场和序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!