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 conclusion that your example works, is wrong.
name
is nottransient
, therefore correctly stored, restored and printed.marks
is declaredstatic
, hence not part of the object’s state and never stored nor restored. It always shows the last written value,4
, despite your first object has written2
to it, because the second object overwrites it with4
before your test even starts.id
is atransient
instance field which is not stored, thus, showing the default value0
. When removing thetransient
keyword, it gets stored and restored, showing3
for the first and6
for the second object.Maybe it would help you, if you add spacing or even the identifiers like
"name="+name+", id="+id+""+", marks="+marks
in the string representationreturned by
toString()
.To add another corner case, producing counter-intuitive behavior, if you add a field
to your class, you will also experience it to show the correct value after restoring, because it is a compile-time constant. So any code referencing this variable will invariably use the constant value and never actually read the instance field, so the fact that it wasn’t restored stays unnoticed. But, of course, such a constant is better declared
static
to avoid wasting memory for a never-read instance field.Another perhaps surprising example would be declaring
transient final
fields in anenum
. They will always appear to show the correct value, because the state ofenum
objects is never stored, but the actual, already initialized, constant objects of thatenum
type are resolved when deserializing anenum
value.Your question is somewhat a duplicate of this:
and
As for the results of your test:
transient
Clearly, the
transient
field (4th character) is not being serialized/deserialized (ABC34->ABC04 and DEF64->DEF04)static
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 then4
, but only4
gets printed. Nothing to do with serialization in this case, simply static field behavior.