对象序列化
Java的对象序列化是将Java对象转换成字节序列,二进制流。
这些字节序列可以保存在磁盘,或通过网络传输。并且可以将这种二进制流恢复成原来的Java对象。
对象的序列化(Serialize)是将JAVA对象写入IO流。
反序列化(Deserialize)是从IO流中恢复该java对象。
为了对象支持序列化,必须让它的类是可序列化的(serializable)。类必须实现下面两个接口之一:
- Serializable
- Externalizable
Serializable是一个标记接口,无需实现任何方法。只表明该类的实例是可序列化的。
public interface Serializable {
}
使用对象流实现序列化
创建一个类,实现Serializable
接口。
使用 ObjectOutputStream 输出流,它是处理流,建立节点流FileOutputStream。
ObjectOutputStream的 writeObject()输出可序列化的对象。
class SA implements Serializable{
private String name;
private int age;
public SA(String name, int age) {
System.out.println("params 构造");
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class SerializableTest {
public static void main(String[] args){
try (
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"))
){
SA sa = new SA("liu", 18);
oos.writeObject(sa);
}
catch (IOException e){
}
}
}
//生成obj.txt
params 构造
readObject()从流中读取对象, 返回Object类型。
try (
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"))
){
SA sa1 = (SA) ois.readObject();
System.out.println(sa1.getName() + " age :" + sa1.getAge());
}
catch (Exception e){
}
//Output
liu age :18
反序列化时要提供对象所属类的class文件,否则会引发ClassNotFoundException。
反序列化无须通过构造器初始化JAVA对象。
如果序列化向文件中写入多个对象,反序列化时要按照实际的写入顺序读取。
当一个可序列化类有多个父类时,这些父类要么有无参的构造器,要么也可序列化。
如果父类是不可序列化的,只是带有无参的构造器,则该父类定义的成员变量值不会序列化到二进制流中。
对象引用的序列化
如果类成员变量是引用类型, 那么这个引用类也是可序列化的。
序列化机制:
- 所有保存到磁盘中的对象都有一个序列化编号
- 序列化对象时,先检查该对象是否被序列化过,只有该对象从未在本次虚拟机中被序列化过,系统才将该对象转换为字节序列化并输出
- 如果已经被序列化过,程序只是输出一个序列化编号,不是重新序列化。
class SA implements Serializable{
private String name;
private int age;
public SA(String name, int age) {
System.out.println("params 构造");
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(