最终瞬态场和序列化 [英] final transient fields and serialization

查看:153
本文介绍了最终瞬态场和序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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 is final.

在示例中缓存 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆