问题
Class members (static) cannot be serialized. The reason is obvious - they are not held by the object(s) of the class. Since they are associated with the class (rather than the object of that class), they are stored separately from the object.
serialVersionUID
is declared as a static field within a class that implements the java.io.Serializable interface something like the following.
private static final long serialVersionUID = 1L;
It is used as a version control in a Serializable
class. If it is not explicitly declared, will be done automatically by JVM, based on various aspects of the Serializable
class, as described by the Java(TM) Object Serialization Specification.
If it is not explicitly declared within the class implementing the Serializable
interface then a warning may issue.
The serializable class
SomeClass
does not declare astatic
final
serialVersionUID
field of typelong
Is it serialized even though it is static
, how or is it an exception to serialization?
回答1:
Serialization is done "magically," with lots of reflection, and has all sorts of special behavior -- including e.g. looking up the static serialVersionUID
of the class.
回答2:
Let me clear you the use of serialVersionUID
while writing and reading objects to/from file.
In below code, I have written two functions writeObject()
and readObj()
writeObject()
is for writing the object in file
readObj()
is for reading the Object from file
package com.msq;
import java.io.Serializable;
public class A implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
int a;
transient int b;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
}
package com.msq;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class B implements Serializable {
/**
*
*/
private static final long serialVersionUID = 123L ;
/**
*
*/
String name;
A a;
public B() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public A getA() {
return a;
}
public void setA(A a) {
this.a = a;
}
public static void main(String[] args) {
//writeObject();
readObj();
}
static void writeObject() {
B b = new B();
b.setName("Musaddique");
A a2 = new A();
a2.setA(5);
a2.setB(10);
b.setA(a2);
ObjectOutputStream write = null;
try {
write = new ObjectOutputStream(new FileOutputStream(
"D:\\serObj.bat"));
write.writeObject(b);
write.flush();
write.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static void readObj() {
ObjectInputStream reader = null;
try {
reader = new ObjectInputStream(
new FileInputStream("D:\\serObj.bat"));
B b1 = (B) reader.readObject();
System.out.println("name: "+b1.getName());
System.out.println("value of a: "+b1.getA().getA());
System.out.println("value of b: "+b1.getA().getB());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Here I have used serialVersionUID = 123L
for class B and serialVersionUID = 1L
for class A and also used transient
keyword for variable b in order to restrict to save the value of b into file.
1) Write data to file then read the file you will get following output
name: Musaddique
value of a: 5
value of b: 0
you wil get value of b: 0 because we have used transient for b.
Now for testing try to write object by the same call but while reading change the serialVersionUID = 765L
then u will get below exception
java.io.InvalidClassException: com.msq.B; local class incompatible: stream classdesc serialVersionUID = 123, local class serialVersionUID = 765
at java.io.ObjectStreamClass.initNonProxy(Unknown Source)
at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
at java.io.ObjectInputStream.readClassDesc(Unknown Source)
at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at com.msq.B.readObj(B.java:81)
at com.msq.B.main(B.java:46)
So, it is necessary to use same serialVersionUID
while reading and writing the object from file.
Also, it is used in RMI calls when you in-corporate classes from one machine to another machine or system.
回答3:
The serialVersionUID
itself is not serialized. At least, not in the same way as the other properties of your object. Instead it is written out to your output destination as part of a special 'header' that contains information required to rebuild the objects being written.
回答4:
Think of serialVersionUID
not as part of the object data being serialized but as part of the class description. The same way that the class name is part of the serialization stream. Full details of the stream format are documented at Grammar for the Stream Format.
来源:https://stackoverflow.com/questions/13918997/how-is-serialversionuid-serialized-in-java