类成员(静态)无法序列化。原因很明显 - 它们不属于班级的对象。由于它们与类(而不是该类的对象)相关联,因此它们与对象分开存储。
serialVersionUID
被声明为实现java.io.Serializable
接口的类中的静态字段,如下所示。
private static final long serialVersionUID = 1L;
它用作Serializable
类中的版本控件。如果没有显式声明,将由JVM根据Serializable
类的各个方面自动完成,如the Java(TM) Object Serialization Specification所述。
如果未在实现Serializable
接口的类中明确声明,则可能会发出警告。
可序列化的类
类型的SomeClass
未声明static
final
serialVersionUID
long
字段
是否序列化,即使它是static
,序列化的例外情况如何或是什么?
答案 0 :(得分:4)
序列化是“神奇地”完成的,具有大量的反射,并且具有各种特殊行为 - 包括例如查找班级的静态 serialVersionUID
。
答案 1 :(得分:2)
让我清楚一下,在向文件写入文件和从文件中读取对象时使用serialVersionUID
。
在下面的代码中,我编写了两个函数writeObject()
和readObj()
writeObject()
用于在文件
readObj()
用于从文件中读取对象
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();
}
}
}
在这里,我使用了{B}的serialVersionUID = 123L
和A类的serialVersionUID = 1L
,并且对变量b使用了transient
关键字,以限制将b的值保存到文件中。< / p>
1)将数据写入文件,然后读取输出后将得到的文件
name: Musaddique
value of a: 5
value of b: 0
你将获得b:0的值,因为我们已经使用了瞬态b。
现在进行测试尝试通过相同的调用来编写对象,但在阅读时更改serialVersionUID = 765L
,那么你将获得以下异常
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)
因此,在从文件中读取和写入对象时,必须使用相同的serialVersionUID
。
此外,当您从一台计算机到另一台计算机或系统的公司内部类时,它将用于RMI调用。
答案 2 :(得分:1)
serialVersionUID
本身未序列化。至少,与对象的其他属性不同。相反,它会作为特殊“标题”的一部分写入输出目标,其中包含重建正在写入的对象所需的信息。
答案 3 :(得分:1)
将serialVersionUID
视为被序列化的对象数据的一部分,但作为类描述的一部分。与类名称是序列化流的一部分的方式相同。有关流格式的完整详细信息,请参见Grammar for the Stream Format。