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()
— cannot be done since the field is final
.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> ();
}
}
Output:
test$X@1a46e30 {}
test$X@190d11 null
The short answer is "no" unfortunately - I've often wanted this. but transients cannot be final.
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.)