JAVA-I/O流-序列化流和反序列化流
一个程序运行时所创建的对象是存储在内存空间里的,那如何对对象进行持久化的存储呢,我们可以用序列化流(ObjectOutputStream)将对象写入文件中从而持久化存储,当然java也提供了反序列化流(ObjectInputStream)将已经序列化的对象重新读取使用。
- Serializable:java.io.Serializable 接口是一个可序列化认证接口,需要序列化的类必须实现此接口,否则将会报NotSerializableException异常。
ObjectOutputStream 序列化流
构造方法
ObjectOutputStream(OutputStream out)
传入一个OutputStream
节点流
方法
Object WriteObject()
使用节点流写入对象
ObjectInputStream 反序列化流
构造方法
ObjectInputStream(InputStream in)
传入一个InputStream
节点流
方法
Object readObject()
使用节点流写入对象
使用Properties类存储键值对并写入本地文件
// 序列化流存储
public static void stroe() throws IOException{
// 目的地
FileOutputStream fos = new FileOutputStream("D:/io1227/bb/cat.ob");
// 创建序列化流
ObjectOutputStream oos = new ObjectOutputStream(fos);
// 写入对象
oos.writeObject(new Cat("green", 1)); // Cat类必须要实现Serializable接口,下文有详细解释
// 释放资源
oos.close();
}
// 反序列化流
public static void getOb() throws IOException, ClassNotFoundException{
// 目的地
FileInputStream fis = new FileInputStream("D:/io1227/bb/cat.ob");
// 反序列化流
ObjectInputStream ois = new ObjectInputStream(fis);
// 从文件中解析对象
Cat cat = (Cat)ois.readObject();// 注意!返回值为Object,需要强制转型
System.out.println(cat.toString());
// 释放资源
ois.close();
}
通过上面的代码通过序列化流和反序列化流实现了最基本的序列化和反序列化,但是又出现新的问题
InvalidClassException异常问题
当一个对象被序列化后,对象所对应的类只要做改动重新编译生成class
文件,此时反序列化就会报InvalidClassException
异常,这正是上述所需要的实现的Serializable
接口导致的,
因为每当类重新编译,Serializable
就会生成新的serialVersionUID
,而序列化时将此时的serialVersionUID
同时写入文件中,从而保证反序列化的正确,当class文件serialVersionUID
改变导致不匹配,就会出现上述错误,我们可以通过定死serialVersionUID
的方式来解决这个问题
private static final long serialVersionUID=123L;
// final表示该量为常量
// 因为声明的是Long类型,不要忘记数字后加L
有些属性我不想被序列化怎么办
这个问题有两个解决方法
- 使用static修饰该属性,这是因为static锁修饰的属性和方法时属于静态共享区而不属于任何对象的,因此不会被序列化。
- 第二个方法是使用瞬态关键字transient修饰该属性,这是为序列化而量身定做的关键字,表示不需要被序列化。