目录
主要知识点:
- writeObject
- writeReplace
- readObject
- readResolve
什么是序列化,什么是反序列化
序列化就是将对象转为字节码的过程,反序列化则是将字节码转换为对象的过程
序列化
JAVA序列化
java.io.ObjectOutputStream代表对象输出流,它的writeObject(Object obj)方法可对参数指定的obj对象进行序列化,把得到的字节序列写到一个目标输出流中。
java.io.ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
只有实现了Serializable和Externalizable接口的类的对象才能被序列化。Externalizable接口继承自 Serializable接口,实现Externalizable接口的类完全由自身来控制序列化的行为,而仅实现Serializable接口的类可以 采用默认的序列化方式 。
通常对象序列化包括如下步骤:
- 创建一个对象输出流,它可以包装一个其他类型的目标输出流,如文件输出流;
- 通过对象输出流的writeObject()方法写对象。
对象反序列化的步骤如下:
- 创建一个对象输入流,它可以包装一个其他类型的源输入流,如文件输入流;
- 通过对象输入流的readObject()方法读取对象。
通过测试代码分析序列化执行过程,通过本文可以理解writeObject,writeReplace方法的执行顺序,以及序列化执行的具体过程。
测试代码
public class Author implements Serializable {
protected int id;
protected String username;
protected String password;
protected String email;
protected String bio;
protected Section favouriteSection;
public Author() {
this(-1, null, null, null, null, null);
}
public Author(Integer id, String username, String password, String email, String bio, Section section) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
this.bio = bio;
this.favouriteSection = section;
}
public Author(int id) {
this(id, null, null, null, null, null);
}
public void setId(int id) {
this.id = id;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public void setEmail(String email) {
this.email = email;
}
public void setBio(String bio) {
this.bio = bio;
}
public void setFavouriteSection(Section favouriteSection) {
this.favouriteSection = favouriteSection;
}
public int getId() {
return id;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public String getEmail() {
return email;
}
public String getBio() {
return bio;
}
public Section getFavouriteSection() {
return favouriteSection;
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
System.out.println("readObject");
in.defaultReadObject();
}
private void writeObject(ObjectOutputStream out) throws IOException{
System.out.println("writeObject");
out.defaultWriteObject();
}
Object writeReplace() throws ObjectStreamException{
System.out.println("writeReplace");
Author replaced=new Author();
replaced.setId(123);
return replaced;
}
@Test
public void testSeria() throws Exception{
Author author=new Author();
author.setId(456);
Serializable result= deserialize(serialize((Serializable)author));
System.out.println(((Author)result).getId());
}
protected byte[] serialize(Serializable value) throws Exception {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(value);
oos.flush();
oos.close();
return bos.toByteArray();
}
protected Serializable deserialize(byte[] value) throws Exception {
ByteArrayInputStream bis = new ByteArrayInputStream(value);
ObjectInputStream ois = new ObjectInputStream(bis);
Serializable result = (Serializable) ois.readObject();
ois.close();
return result;
}
测试结果
上面的测试代码我们序列化的是ID是456的Author对象,但是反序列化后的对象确实12