Question of the Week #100
What's the purpose of the transient keyword?
1 messages · Page 1 of 1 (latest)
What's the purpose of the transient keyword?
Serialization can be used to convert an object to a different format that can be stored or transferred and then be deserialized to a different format.
For example, binary serialization (using ObjectOutputStream/ObjectInputStream) can do that automatically for classes implementing Serializable:
public class SomeDataClass implements Serializable {
private String someString;
private int someInt;
public SomeDataClass(String someString, int someInt){
this.someString = Objects.requireNonNull(someString);
this.someInt = someInt;
}
@Override
public String toString(){
return "SomeDataClass(someString=" + someString + ", someInt=" + someInt + ")";
}
}
//write an object of that class to a file
SomeDataClass obj = new SomeDataClass("Hello World", 1337);
try(ObjectOutputStream oos = new ObjectOutputStream(Files.newOutputStream(Path.of("object.dat")))) {
oos.writeObject(obj);//write the object to the ObjectOutputStream which serializes it and passes it to the underlying OutputStream
}
//read an object from that file
SomeDataClass obj;
try(ObjectInputStream ois = new ObjectInputStream(Files.newInputStream(Path.of("object.dat")))){
obj = (SomeDataClass)ois.readObject();//WARNING: Deserialization (of untrusted data) is dangerous
}
It should be noted that (de)serialization can lead to many issues including compatibility, construction of invalid objects (e.g. deserialized data is typically not validated on construction) and deserialization of untrusted data can lead to security vulnerabilities (from denial of service to remote code execution, see also the Javadoc of Serializable). Because of these issues, binary (de)serialization using ObjectInputStream/ObjectOutputStream should be avoided in most cases.
The transient keyword can be used to exclude some fields from serialization. For example, if someInt is marked transient, it will not be included in the serialized form and will be 0 when deserialized.
public class SomeDataClass implements Serializable {
private String someString;
private transient int someInt;
public SomeDataClass(String someString, int someInt){
this.someString = Objects.requireNonNull(someString);
this.someInt = someInt;
}
@Override
public String toString(){
return "SomeDataClass(someString=" + someString + ", someInt=" + someInt + ")";
}
}
Some third-party serialization libraries (like gson) also consider this keyword on fields and ignore transient fields during (de)serialization.
The transient keyword marks fields of a class as being excluded from the serialized state of an object. When a class is marked as serializable (implements the Serializable interface), the JVM will write the object's state during a serialization operation, such as with the ObjectOutputStream#writeObject(Object obj) method. Fields marked as transient will be excluded from that mechanism.
On the other side of the process, when objects of that class are deserialized (e.g. read with ObjectInputStream#readObject()), the transient fields will not be populated. The developer must account for these uninitialized fields by either setting them in the special readObject() method of the class, or by otherwise working around the empty value.