serialVersionUID缺少a时,Eclipse发出警告。
The serializable class Foo does not declare a static final serialVersionUID field of type long
java.io.Serializable 你可能会得到的有关文档的解释很好:
序列化运行时与每个可序列化的类关联一个版本号,称为serialVersionUID,在反序列化过程中使用该版本号来验证序列化对象的发送者和接收者是否已加载了该对象的与序列化兼容的类。如果接收者为对象加载的类serialVersionUID与相应的发送者的类不同,则反序列化将导致 InvalidClassException。可序列化的类可以serialVersionUID通过声明一个serialVersionUID必须为static,final和type 的字段来显式声明其自身long:
serialVersionUID
InvalidClassException
static
final
type
long
ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;
如果可序列化的类没有显式声明 serialVersionUID,则序列化运行时将根据serialVersionUID该类的各个方面为该类计算一个默认值,如Java对象序列化规范中所述。但是,强烈建议所有可序列化的类显式声明serialVersionUID值,因为默认serialVersionUID计算对类详细信息高度敏感,而类详细信息可能会根据编译器的实现而有所不同,因此可能导致InvalidClassExceptions反序列化期间发生意外情况。因此,为了保证serialVersionUID不同Java编译器实现之间的值一致,可序列化的类必须声明一个显式serialVersionUID值。还强烈建议明确serialVersionUID声明尽可能使用private修饰符,因为此类声明仅适用于立即声明的类serialVersionUID字段,不能用作继承成员。
InvalidClassExceptions
private
首先,我需要解释什么是序列化。
序列化 允许将对象转换为流,以便通过网络发送该对象,或者保存到文件或保存到DB以供使用。
有一些序列化规则。
Serializable
java.io.InvalidClassException
当Object被序列化,Java运行时关联的序列版本号又名的serialVersionID。
我们需要serialVersionID的位置: 在反序列化期间,验证发送者和接收者在序列化方面是否兼容。如果接收者给类加载了另一个类,serialVersionID反序列化将以结束InvalidClassCastException。 可序列化的类可以serialVersionUID通过声明一个serialVersionUID必须为静态,最终且类型为long的字段来显式声明其自身。
让我们尝试一个例子。
import java.io.Serializable; public class Employee implements Serializable { private static final long serialVersionUID = 1L; private String empname; private byte empage; public String getEmpName() { return name; } public void setEmpName(String empname) { this.empname = empname; } public byte getEmpAge() { return empage; } public void setEmpAge(byte empage) { this.empage = empage; } public String whoIsThis() { StringBuffer employee = new StringBuffer(); employee.append(getEmpName()).append(" is ).append(getEmpAge()).append(" years old ")); return employee.toString(); } }
创建序列化对象
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class Writer { public static void main(String[] args) throws IOException { Employee employee = new Employee(); employee.setEmpName("Jagdish"); employee.setEmpAge((byte) 30); FileOutputStream fout = new FileOutputStream("/users/Jagdish.vala/employee.obj"); ObjectOutputStream oos = new ObjectOutputStream(fout); oos.writeObject(employee); oos.close(); System.out.println("Process complete"); } }
反序列化对象
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class Reader { public static void main(String[] args) throws ClassNotFoundException, IOException { Employee employee = new Employee(); FileInputStream fin = new FileInputStream("/users/Jagdish.vala/employee.obj"); ObjectInputStream ois = new ObjectInputStream(fin); employee = (Employee) ois.readObject(); ois.close(); System.out.println(employee.whoIsThis()); } }
注意:现在更改Employee类的serialVersionUID并保存:
private static final long serialVersionUID = 4L;
并执行Reader类。不执行Writer类,你将获得异常。
Exception in thread "main" java.io.InvalidClassException: com.jagdish.vala.java.serialVersion.Employee; local class incompatible: stream classdesc serialVersionUID = 1, local class serialVersionUID = 4 at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616) at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623) at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371) at com.krishantha.sample.java.serialVersion.Reader.main(Reader.java:14)