JavaSE|序列化流ObjectOutputStream、ObjectInputStream

概念

序列化流:把对象按照流一样的方式存入文本文件或者在网络中传输。对象 – 流数据(ObjectOutputStream)
反序列化流:把文本文件中的流对象数据或者网络中的流对象还原成对象。流数据 – 对象(ObjectInputStream)

操作例程

  • ObjectOutputStream类的方法 void writeObject(Object obj)
    将指定的对象写入 ObjectOutputStream。
    该对象必须被序列化,否则报错java.io.NotSerializableException
  • ObjectInputStream类的方法 Object readObject()
    从 ObjectInputStream 读取对象。
  • java.io.Serializable 接口:
    类通过实现 java.io.Serializable 接口以启用其序列化功能。
    未实现此接口的类将无法使其任何状态序列化或反序列化。
    可序列化类的所有子类型本身都是可序列化的。
    序列化接口没有方法或字段,仅用于标识可序列化的语义。
    类似于这种没有方法的接口被称为标记接口
	public class Person implements Serializable{
	private String name;
	private int age;
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	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;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
}
	public class ObjectStreamDemo {

	/**
	 * @param args
	 * @throws IOException 
	 * @throws ClassNotFoundException 
	 */
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		// 由于我们要对对象进行序列化,所以我们先自定义一个类
		// 序列化数据其实就是把对象写到文本文件
		//write();
		
		read();

	}

	private static void read() throws IOException, IOException, ClassNotFoundException {

		// 创建反序列化对象
		ObjectInputStream ois = new ObjectInputStream(new FileInputStream("oos.txt"));
		
		Object obj = ois.readObject();
		
		ois.close();
		
		System.out.println(obj);
		
		
	}

	private static void write() throws IOException, IOException {
		// 创建序列化流对象
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("oos.txt"));
		
		// 创建对象
		Person p = new Person("林青霞",27);
		
		oos.writeObject(p);
		
		// 释放资源
		oos.close();
	}

}

例程改进:serialVersionUID

在上面的程序中,如果改变Person中的成员变量,而还想读取之前写的数据时,会产生异常java.io.InvalidClassException: cn.itcast_07.Person; local class incompatible……

为什么会产生问题?
Person类实现了序列化接口,那么它本身有一个序列化标记值。假设改变前这个值是100,则:
以前:

Person.class -- id = 100
write数据:oos.txt -- id = 100
read数据:oos.txt -- id = 100

改变后:

Person.class -- id = 200
write数据:oos.txt -- id = 100
read数据:oos.txt -- id = 100

读取文件时,会和class文件中的id进行匹配,故出现异常。
所以讲这个id设置成固定值,就不会出现这个问题了。

有了这个序列化值后,我们对类进行任何改动,它读取以前的数据是没有问题的。
对实现序列化接口的类,add generated serial version ID,如下所示:

	public class Person implements Serializable{

	private static final long serialVersionUID = -8345153069362641443L;

	private String name;
	private int age;
	
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	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;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
}

transient关键字

使用transient关键字关键字声明不需要序列化的成员变量

面试题

  1. 什么时候序列化
    把对象写入文本文件或者在网络中传输
  2. 如何实现序列化
    让被序列化对象所属的类实现序列化接口
  3. 什么是反序列化
    把文本文件中的流对象数据或者网络中的流对象还原成对象。流数据 – 对象(ObjectInputStream)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值