I was reading about transient and final keyword and I found the answer that we can't use transient keyword with final keyword. I tried and got confused because here it working fine.
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
public class SerExample{
public static void main(String... args){
Student foo = new Student(3,2,"ABC");
Student koo = new Student(6,4,"DEF");
try
{
FileOutputStream fos = new FileOutputStream("abc.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(foo);
oos.writeObject(koo);
oos.close();
fos.close();
}
catch(Exception e){/**/}
try{
FileInputStream fis = new FileInputStream("abc.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
System.out.println(ois.readObject());
System.out.println(ois.readObject());
fis.close();
ois.close();
}catch(Exception e){/**/}
}
}
Here is the Serializable Student class Code:
class Student implements Serializable{
private transient final int id;
private transient static int marks;
private String name;
public Student(int id, int marks, String name){
this.id = id;
this.marks = marks;
this.name = name;
}
public Student(){
id=0;
}
@Override
public String toString(){
return (this.name + this.id + this.marks);
}
}
Code output with transient keyword.
ABC04
DEF04
Output without transient keyword.
ABC34
DEF64
Can you explain why it's working fine? is there a bug?
At the end what should be behavior of transient with final keyword?
Your question is somewhat a duplicate of this:
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.
and
Any field that is declared transient is not serialized. Moreover, according to this blog post, field values are not even initialized to the values that would be set by a default constructor. This creates a challenge when a transient field is final.
Code output with transient keyword. ABC04 DEF04
Output without transient keyword. ABC34 DEF64
Clearly, the transient
field (4th character) is not being serialized/deserialized (ABC34->ABC04 and DEF64->DEF04)
The static
field (5th char) is also not being deserialized! It's simply because your are performing the operation in the same memory space, and the static field remains across all instances. So when you set the static field on student, and later deserialize another student, of course the static field still has the same value!
This also explain why in your test you first set the static field to 2
and
then 4
, but only 4
gets printed. Nothing to do with serialization in this case, simply static field behavior.