预备知识
单词发音
英 [sɪərɪəlaɪ'zəbl]
美 [sɪərɪrlaɪ'zəbl]
什么叫序列化
下面引入百度百科的的一段关于序列化
的一段解析
序列化 (Serialization)将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
在java中Serializable接口类的定义如下:
package java.io;
public interface Serializable {
}
特性讲解
- 实现(implement)了java.io.serializable接口的类可以被序列化。没有实现这个接口的类将不能
序列化
和反序列化
。该接口没有属性和方法,只作为可以被序列化的标识。 - 如果想要非序列化的子类被序列化,子类必须负责保存和恢复父类的
public
,protected
以及package
类型的属性。如果实现了Serializable
接口不存在一个无参数的构造函数时,在运行时反序化会抛出错误。 - 在反序列化过程中,非序列化类的字段将使用该类的
public
或protected
的无参数构造函数初始化;无参数构造函数必须可被序列化的子类访问;可序列化子类的字段将从流中恢复。 - 序列化运行时与每个可序列化类都会存在一个称为
serialVersionUID
属性值,它在反序列化期间用于验证序列化对象的发送方和接收方已经为该对象加载了与序列化兼容的类。如果接收方为对象加载的类与相应发送方的类的serialVersionUID
不同,则反序列化将导致InvalidClassException
- 如果用户没有自己声明一个
serialVersionUID
,接口会默认生成一个与calss细节高度敏感的serialVersionUID
;
案例讲解
我们先创建一个实现了Serializable接口的实体类Person,代码如下:
package com.oneape;
import java.io.Serializable;
/**
* described :
* Created by oneape on 2018-12-26 17:32.
* Modify:
*/
public class Person implements Serializable {
private String name;
private int sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
}
然后去序列化和反序列化:
package com.oneape;
import java.io.*;
/**
* described :
* Created by oneape on 2018-12-26 18:11.
* Modify:
*/
public class PersonSerialTest {
public static void main(String[] args) throws Exception {
serializePerson();
Person person = deserializePerson();
System.out.println(person.getName() + ": " + person.getSex());
}
private static void serializePerson() throws IOException {
Person person = new Person();
person.setName("张三");
person.setSex(1);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("person.txt")));
oos.writeObject(person);
System.out.println("序列化成功");
oos.close();
}
private static Person deserializePerson() throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("person.txt")));
Person person = (Person) ois.readObject();
System.out.println("反序列化成功");
return person;
}
}
运行结果如下:
序列化成功
反序列化成功
张三: 1
Process finished with exit code 0
扩散思考
我们将类Person
改成不实现Serializable
接口这后再运行PersonSerialTest
试试,结果如下:
Exception in thread "main" java.io.NotSerializableException: com.oneape.Person
at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
at com.oneape.PersonSerialTest.serializePerson(PersonSerialTest.java:24)
at com.oneape.PersonSerialTest.main(PersonSerialTest.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Process finished with exit code 1
加分项
感兴趣的同学可以再去看一下如下的几个类是怎么实现writeObject
,readObject
的
- java.io.ObjectOutputStream
- java.io.ObjectInputStream
- java.io.ObjectOutput
- java.io.ObjectInput