Java IO操作之对象序列化

简介

序列化是做什么用的?

序列化(Serialize):将在内存中的对象变为了指定格式的二进制数据。目的是将对象保存在磁盘中,或者允许在网络中直接传输对象。

序列化与反序列化

对象的序列化(Serialize)指将一个 Java 对象写入 IO 流中,与此对应的是,对象的反序列化(Deserialize)则是指的是从 IO 流中恢复该 Java 对象。序列化与反序列化需要用到的类如下:

  • 序列化类:java.io.ObjectOutputStream 将对象变为了指定格式的二进制数据;
  • 反序列化类:java.io.ObjectInputStream 可以将序列化的对象转换回对象内容;

实现序列化操作类:ObjectOutputStream

  • 构造方法:public ObjectOutputStream(OutputStream out) throws Exception
  • 输出对象:public final writeObject(Object obj) throws Exception;

如何序列化?

如果要序列化对象,那么其所在的类一定要实现 java.io.Serializable 接口。但是这个接口里面没有任何的操作方法存在,因为它是一个标识接口。

代码实例

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;


//如果不想加上序列化的那段代码,可以使用注解: @SuppressWarnings("serial")		// 实现序列化接口
class Book implements Serializable {
	// 由于序列化需要给类一个指定的序列化编码,所以需要加上这端代码
	private static final long serialVersionUID = 729234114635241116L;
	
	private String tiltle;
	private double price;

	public Book(String title, double price) {
		this.tiltle = title;
		this.price = price;
	}

	@Override
	public String toString() {
		return "书名《" + this.tiltle + "》,价格:" + this.price + "元。";
	}
}

public class Test {

	// 序列化
	public static void ser() throws Exception {
		ObjectOutputStream oos = new ObjectOutputStream(
				new FileOutputStream(new File("e:" + File.separator + "book.ser")));
		oos.writeObject(new Book("Java从入门到精通", 88.8));
		oos.close();	// 关闭流
	}

	// 反序列化
	public static void dser() throws Exception {
		ObjectInputStream ois = new ObjectInputStream(
				new FileInputStream(new File("e:" + File.separator + "book.ser")));
		Object obj = ois.readObject();
		Book book = (Book) obj;
		System.out.println(book);
		ois.close();	// 关闭流
	}

	public static void main(String[] args) throws Exception {
		ser();	// 序列化
		// dser();	// 反序列
	}
}

序列化结果:
序列化结果

反序列结果:

书名《Java从入门到精通》,价格:88.8元。

transient 关键字

序列化操作时,是将整个对象所有的属性内容进行了保存,现在有些属性的内容不需要被保存,就可以通过 transient 关键字来定义。定义如下:

private transient String title;

如果通过 transient 关键字修改了 title 属性,那么执行序列化之后,再执行反序列化的时候,就获取不到之前设置进去的值了。

当程序序列化一个 Teacher 对象时,如果该 Teacher 类对象持有一个 Person 类对象的引用,为了在反序列化是可以正常恢复该 Teacher 类对象,程序就会顺带将该 Person 对象也进行序列化,所以 Person 类也必须要是可以序列化的。

Java 序列化机制采用了一种特殊序列化算法,其算法内容如下:

  • 所有保存到磁盘中的对象都有一个序列化编号
  • 当程序视图序列化一个对象时,程序将先检查该对象是否已经序列化过,只有改对象从未被序列化(在本次的虚拟机中序列化),系统才会将该对象转换成字节序列并输出
  • 如果某个对象已经序列化过了,程序只是直接输出一个序列化编号,而不是再次重新序列化改对象。

多次序列化同一个对象

由于 Java 序列化机制使然,如果多次序列化同一个 Java 对象,只有第一次序列化时才会把该 Java 对象转换成直接序列并输出,这样可能引起一个潜在的问题:

当程序序列化一个可变对象时,只有第一次使用 writeObject() 方法输出时,才会将该对象转换成字节序列并输出,当程序再次调用 writeObject() 方法时,程序只是输出前面的序列化编号,及时后面改对象的实例值已经被改变,改变的实例变量值也不会被输出。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wayfreem

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值