什么是对象序列化?
对象序列化是指将对象转换为二进制数据流的操作,从而使对象的状态信息转换为可以存储或传输的形式。通俗点,我觉得就是把对象的状态转换为一个字符串(这个字符串是乱码的,谁也看不懂)。
为什么要有对象序列化?
比如我们创建了一个对象:
Book book=new Book("你好 旧时光");
当这句代码运行的时候,我们的程序会在内存开辟一个堆内存保存new出来的这个book实体对象的内容,开辟一个栈内存保存一个变量book,内容为堆内存中book对象的地址。简单的说,对象book是我们的程序运行时并且在电脑通电的情况下在内存中维护的一种东西,如果我们的程序停止运行了或者电脑断电了,对象book将不复存在。那么如何把对象book的内容保存在磁盘上呢(也就是说在没电时继续保留着)?这时就需要把对象book序列化,也就是说把book对象的内容转换成一个字符串的形式,然后再保存在磁盘上。除此之外,我们通过http协议把对象发送到客户端也是通过序列化完成的。
什么是反序列化?
反序列化就是解析对象序列化后得到的字符串还原为对象。
实现序列化与反序列化
需要序列化的对象的类必须先声明实现Serializable接口,这样标志着该类的对象可以被序列化。然后java提供有两个类分别进行序列化和反序列化操作。
1.序列化类:java.io.ObjectOutputStream
构造方法(其中一个):
public ObjectOutputStream(OutputStream out) throws IOException
ObjectOutputStream是OutputStream的子类,在构造方法中又接收OutputStream对象的参数,这样的设计和PrintStream一样,都是装饰器设计模式。
向输出流写入对象序列化后的字符串:
public final void writeObject(Object obj) throws IOException
2.反序列化类:java.io.ObjectInputStream
构造方法(其中一个),也是装饰器模式的设计:
public ObjectInputStream(InputStream in)throws IOException
从输入流读取反序列化后的对象:
public final Object readObject() throws IOException,ClassNotFoundException
示例:将一个City对象序列化写入到文件,再读取文件反序列化还原对象
package test;
import java.io.Serializable;
public class City 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;
}
public City(String name, int id) {
this.name = name;
this.id = id;
}
@Override
public String toString() {
return "City{" +
"name='" + name + '\'' +
",id=" + id +
'}';
}
}
import test.City;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
City city=new City("杭州",1);
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(new File("e:\\test.txt")));
out.writeObject(city);
ObjectInputStream in=new ObjectInputStream(new FileInputStream(new File("e:\\test.txt")));
City city1=(City) in.readObject();
System.out.println(city1);
}
}
运行结果:
City{name='杭州',id=1}
打开test.txt是一串对象序列化后的字符串:
sr test.City莮媚 I idL namet Ljava/lang/String;xp t 鏉窞
假如不想对该对象的某属性做序列化操作,可以在该属性前面加transient修饰。例如我在City类的name属性前面加上transient修饰,那么运行结果将变为:
City{name='null',id=1}