1.什么是序列化
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
序列化的好处在于可将任何实现了Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原
序列化是 RMI(Remote Method Invoke – 远程方法调用)过程的参数和返回值都必须实现的机制,而 RMI 是 JavaEE 的基础。因此序列化机制是 JavaEE 平台的基础
2.实现序列化
序列化(Serialize):用ObjectOutputStream类将一个Java对象写入IO流中。
反序列化(Deserialize):用ObjectInputStream类从IO流中恢复该Java对象。
ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量。
如果需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
Serializable
Externalizable
通常我们用Serializable接口。
(1)凡是实现Serializable接口的类都有一个表示序列化版本标识符的静态变量:
private static final long serialVersionUID;
serialVersionUID用来表明类的不同版本间的兼容性。
如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的。若类的源代码作了修改,serialVersionUID 可能发生变化。因此建议显示声明。
(2)显示定义serialVersionUID的用途:
希望类的不同版本对序列化兼容,因此需确保类的不同版本具有相同的serialVersionUID 。
不希望类的不同版本对序列化兼容,因此需确保类的不同版本具有不同的serialVersionUID。
(3)使用对象流序列化对象。
如果某个类的字段不是基本数据类型或 String 类型,而是另一个引用类型,那么这个引用类型必须是可序列化的,否则拥有该类型的 Field 的类也不能序列化。若某个类实现了 Serializable 接口,该类的对象就是可序列化的。
定义一个类实现序列化接口:
class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String name;
public Employee() {
super();
}
public Employee(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + "]";
}
}
这样这个类的对象就可以进行序列化和反序列化了。
下面来测试一下:
public void testSerializable() {
FileOutputStream fos = null;
FileInputStream fis = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
try {
fos = new FileOutputStream("Serializable.txt");
fis = new FileInputStream("Serializable.txt");
oos = new ObjectOutputStream(fos);
ois = new ObjectInputStream(fis);
Employee employee = new Employee(1, "kkk");
// 序列化
oos.writeObject(employee);
oos.flush();
// 反序列化
Object obj = ois.readObject();
System.out.println(obj);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这个测试将Employee对象写入Serializable.txt文件中,然后再从Serializable.txt文件中读出来。
by Karl