最终瞬态字段的序列化/反序列化

时间:2021-01-18 03:22:32

标签: java serialization deserialization final transient

this 问题中,final transient 字段在序列化后不能设置为任何非默认值。那么为什么我有 3 个 aVar1 变量和 s3 个 aVar3 变量?

import java.io.*;
import java.util.*;

class Test
{
    public static void main(String[] args) throws IOException, ClassNotFoundException
    {
        A a1 = new A();
    
        // save a1 to file
        FileOutputStream fileOutput = new FileOutputStream("a.dat");
        ObjectOutputStream outputStream = new ObjectOutputStream(fileOutput);
        outputStream.writeObject(a1);
        fileOutput.close();
        outputStream.close();
    
        // load a1 from file
        FileInputStream fiStream = new FileInputStream("a.dat");
        ObjectInputStream objectStream = new ObjectInputStream(fiStream);
        a1 = (A) objectStream.readObject();
        fiStream.close();
        objectStream.close();
    
        // fields after deserialization
        System.out.println(a1.aVar1); // 3
        System.out.println(a1.aVar2); // null
        System.out.println(a1.aVar3); // s3
        System.out.println(a1.aVar4); // null
    }
}

class A implements Serializable
{
    public final transient int aVar1 = 3;
    public final transient Map <Object, Object>  aVar2 = new HashMap <> ();
    public final transient String aVar3 = "s3";
    public final transient String aVar4 = new String("s4");
}

2 个答案:

答案 0 :(得分:1)

在反序列化过程中,不会调用对象的构造函数。这是JVM处理的一个特殊的对象实例化过程。

对于 aVar2 和 aVar4,调用 Hashmap 和字符串构造函数。所以这些变量被赋予了默认值(空)。

对于 aVar1 和 aVar3,一些常量表达式被分配给它们。这些称为编译时常量。

编译时常量的条件是

  1. 它们必须被声明为最终的
  2. 它们是原始数据类型或字符串
  3. 它们必须用它们的声明进行初始化。
  4. 它们的值必须是常量表达式。

重新影响编译时常量,反序列化后这些值将保留。

答案 1 :(得分:0)

aVar1aVar3编译时常量,它们永远不会通过实例字段读取,而是直接读取。

所以看起来您实际上执行了 a1.aVar1,即您访问了一个实例字段 - 但您从未这样做过。这就像直接做:System.out.println(3)

另一方面,根据 compile time constants,其余的实例字段不是 JLS

相关问题