简体   繁体   中英

Serialization/Deserialization of the final transient fields

In this question says that final transient fields can not be set to any non-default value after serialization. So why I have 3 for aVar1 variable and s3 for aVar3 variable?

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");
}

During deserialization, the constructor of the object is not called. This is a special object instantiation process handled by the JVM.

For aVar2 and aVar4, the Hashmap and string constructor is called. So these variables are assigned default values(null).

For aVar1 and aVar3, some constant expression is assigned to them. These are called compile time constants.

The conditions for compile time constants are

  1. They must be declared final
  2. They are of primitive data types or String
  3. They must be initialized with their declaration.
  4. Their value must be constant expression.

Compile time constants are reaffected and these values will be retained after deserialisation.

aVar1 and aVar3 are compile time constants , these are never read via instance fields, but always directly.

So it looks like you actually do a1.aVar1 , ie you access an instance field - but you never do. It's like doing: System.out.println(3) , directly.

On the other hand, the rest of the instance fields are not compile time constants , according to the JLS .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM