序列化
Java API中java.io.Serializable接口源码:
public interface Serializable {
}
可以发现Serializable接口没有方法和字段,仅用于标识可序列化的类。不实现此接口的类的任何字段(属性)都不能序列化和反序列化。那么什么是序列化和反序列化呢?
序列化
把原本在内存中的对象状态 变成可存储或传输的过程称之为序列化。序列化之后,就可以把序列化后的内容写入磁盘,或者通过网络传输到别的机器上。
序列化前的对象和反序列化后得到的对象,内容是一样的(且对象中包含的引用也相同),但两个对象的地址不同。换句话说,序列化操作可以实现对任何可Serializable对象的”深度复制(deep copy)"。
序列化场景
- 当你想把的内存中的对象状态保存到一个文件中或者数据库中,以便可以在以后重新创建精确的副本
- 当你想用套接字在网络上传送对象的时候(从一个应用程序域发送到另一个应用程序域中)
- 当你想通过RMI传输对象的时候;
特性
- 实现了java.io.serializable接口的类可以被序列化。没有实现这个接口的类将不能
序列化
和反序列化
。该接口没有属性和方法,只作为可以被序列化的标识。 - 如果想要非序列化的子类被序列化,子类必须负责保存和恢复父类的
public
,protected
以及package
类型的属性。如果实现了Serializable
接口不存在一个无参数的构造函数时,在运行时反序化会抛出错误。 - 在反序列化过程中,非序列化类的字段将使用该类的
public
或protected
的无参数构造函数初始化;无参数构造函数必须可被序列化的子类访问;可序列化子类的字段将从流中恢复。 - 序列化运行时与每个可序列化类都会存在一个称为
serialVersionUID
属性值,它在反序列化期间用于验证序列化对象的发送方和接收方已经为该对象加载了与序列化兼容的类。如果接收方为对象加载的类与相应发送方的类的serialVersionUID
不同,则反序列化将导致InvalidClassException
- 如果用户没有自己声明一个
serialVersionUID
,接口会默认生成一个与calss细节高度敏感的serialVersionUID
;
代码实现
package com;
import java.io.Serializable;
public class SerializableTest implements Serializable {
private String name;
private int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
package com.javapandeng.controller;
import java.io.*;
public class Test {
public static void main(String[] args) throws Exception{
serializableTest();
SerializableTest test = deserializeTest();
System.out.println(test.getId() + ":" + test.getName());
}
//序列化
private static void serializableTest() throws IOException {
SerializableTest test = new SerializableTest();
test.setName("小明");
test.setId(1);
ObjectOutputStream obs = new ObjectOutputStream(new FileOutputStream(new File("test.txt")));
obs.writeObject(test);
obs.close();
}
//反序列化
private static SerializableTest deserializeTest() throws Exception {
ObjectInputStream obs = new ObjectInputStream(new FileInputStream(new File("test.txt")));
SerializableTest test = (SerializableTest) obs.readObject();
return test;
}
}