首先,我需要解释什么是序列化。
序列化 允许将对象转换为流,以便通过网络发送该对象,或者保存到文件或保存到DB以供使用。
有一些序列化规则。
- 仅当对象的类或其超类实现
Serializable
接口时,该对象才可序列化 - 一个对象是可序列化的(本身实现了
Serializable
接口),即使其超类不是。但是,可序列化类的层次结构中的第一个超类(不实现Serializable接口)必须具有无参数构造函数。如果违反此规定,则readObject()将在运行时生成java.io.InvalidClassException
- 所有原始类型都是可序列化的。
- 暂态字段(带有暂态修饰符)未序列化(即,未保存或恢复)。实现Serializable的类必须标记不支持序列化的类(例如文件流)的瞬态字段。
- 静态字段(带有static修饰符)未序列化。
当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 = newFileOutputStream("/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 = 4at 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)



