将程序运行过程中的某些对象进行保存(序列化),
在需要的时候再读取(反序列化)出来使用。
写对象:ObjectOutputStream
读对象:ObjectInputStream
要使用序列化功能,必须实现Serializable接口
静态成员和transient修饰的字段,将忽略,不被序列化
容易出错的地方:
当未显示声明序列化ID值,而是由程序根据类的各方面信息自动计算,当类发生改变后,计算出来的值就会前后不一致,导致异常发生:
Exception in thread "main" java.io.InvalidClassException: com.gc.stream.Person; local class incompatible: stream classdesc serialVersionUID = -5575955724459671672, local class serialVersionUID = -2912268919946746231
如,写的时候,Person的name属性是private的,使用ObjectOutputStream将对象写到了磁盘上;
写好了之后,由于某些原因,对Person类进行了改变,name属性变为public了;
当使用ObjectInputStream进行反序列化时,发现前后的序列化ID不同,于是出现问题!
解决办法:
实现Serializable接口的同时,显示声明serialVersionUID值,保存序列化ID前后一致!即时类的信息发生了改变,但是其serialVersionUID值是不变的!
这样,即时是写好对象后,删除了person的name属性,一样能够正确反序列对象。
Person类
package com.gc.stream;
import java.io.Serializable;
public class Person implements Serializable {
/**
* serialVersionUID 确保反序列化不因为类的属性发生修改而抛异常:java.io.InvalidClassException
*/
private static final long serialVersionUID = -5575955724459671672L;//根据类名,字段类型,修饰符等信息计算出来的一个long类型值,每个类都唯一,不会重复
public String name;
private int age;
public Person(String name, int age) {
super();
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;
}
}
package com.gc.stream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
/**
* 将对象由堆内存存储到硬盘上---延长对象的声明周期
*
*/
public class ObjectPersistDemo {
public static void main(String[] args) throws IOException, ClassNotFoundException {
//保存对象到磁盘---对象的序列化
writerObjToDisk();
//从磁盘文件恢复对象---对象的反序列化
readObjFromDisk();
}
private static void writerObjToDisk() throws IOException {
Person p1 = new Person("张晓玲",23);
Person p2 = new Person("李四",24);
OutputStream out = new FileOutputStream("temp\\person.object");
ObjectOutputStream oos = new ObjectOutputStream(out);
oos.writeObject(p1);
oos.writeObject(p2);
oos.close();
}
private static void readObjFromDisk() throws IOException, ClassNotFoundException {
InputStream in = new FileInputStream("temp\\person.object");
ObjectInputStream ois = new ObjectInputStream(in);
try {
while(true) {
//再次调用readObject()时,将读取下一个对象
Person p = (Person)ois.readObject();
System.out.println(p.getName()+","+p.getAge());
}
} catch(EOFException e) {
System.out.println("对象读取完毕");
} finally {
ois.close();
}
}
}