The following code throws a NullPointerException
.
import java.io.*;
public class NullFinalTest {
public static void main(String[] args) thr
As pointed out before, the declaration below does not work as one might expect:
transient final Object foo = new Object()
The transient
keyword will prevent the member from being serialized. Initialization with a default value is not honored during deserialization, therefore foo
will be null
after deserialization.
The final
keyword will prevent you from modifiying the member once it has been set. This means you're stuck with null
forever on a deserialized instance.
In any case you will need to drop the final
keyword. This will sacrifice immutability, but should not usually be an issue for private
members.
Then you have two options:
readObject()
transient Object foo = new Object();
@Override
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
foo = new Object();
}
When creating a new instance, foo
will be initialized to its default value. When deserializing, your custom readObject()
method will take care of that.
This will work on JRE but not on Android, as Android's implementation of Serializable
lacks the readObject()
method.
Declaration:
transient Object foo;
On access:
if (foo == null)
foo = new Object();
doStuff(foo);
You would have to do this wherever in your code you access foo
, which may be more work and more error-prone than the first option, but it will work on JRE and Android alike.