在 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");
}
答案 0 :(得分:1)
在反序列化过程中,不会调用对象的构造函数。这是JVM处理的一个特殊的对象实例化过程。
对于 aVar2 和 aVar4,调用 Hashmap 和字符串构造函数。所以这些变量被赋予了默认值(空)。
对于 aVar1 和 aVar3,一些常量表达式被分配给它们。这些称为编译时常量。
编译时常量的条件是
重新影响编译时常量,反序列化后这些值将保留。
答案 1 :(得分:0)
aVar1
和 aVar3
是编译时常量,它们永远不会通过实例字段读取,而是直接读取。
所以看起来您实际上执行了 a1.aVar1
,即您访问了一个实例字段 - 但您从未这样做过。这就像直接做:System.out.println(3)
。
另一方面,根据 compile time constants
,其余的实例字段不是 JLS
。