Java IO序列化与反序列化及自定义序列化

序列化:把对象转换为字节序列的过程称为对象的序列化。通过实现Serializable接口实现序列化。

反序列化:把字节序列恢复为对象的过程称为对象的反序列化。

自定义序列化:通过实现Externalizable接口,重写它的方法writeExternal()和readExternal()。

package com.hmi.io;

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

public class ObjectIOTest {
	public static void main(String[] args) throws IOException,
			ClassNotFoundException {
		// 创建student对象
		Student s1 = new Student("小明", 1, 90, 18);
		Student s2 = new Student("小红", 2, 100, 20);
		// 创建输出管道
		FileOutputStream fos = new FileOutputStream("student.dat");
		ObjectOutputStream out = new ObjectOutputStream(fos);
		// 写入s1,s2对象流
		out.writeObject(s1);
		out.writeObject(s2);
		// 关闭输出管道
		out.close();
		// 创建输入管道
		FileInputStream fis = new FileInputStream("student.dat");
		ObjectInputStream in = new ObjectInputStream(fis);

		// 无法通过一个准确的数值判断是否读完,就运用try ... catch语句,当数据读完抛异常时跳出while循环
		// 反序列化输出对象
		try {
			while (true) {
				Object o = in.readObject();
				System.out.println(o);
			}
		} catch (Exception e) {
			System.out.println("文件读完了");
		}
		// 关闭输入管道
		in.close();
	}
}

// Student类实现Serializable接口实现序列化
class Student implements Serializable {

	private static final long serialVersionUID = -5139397063007446571L;

	String name;
	int id;
	double score;
         // 可以阻止该变量被序列化到文件中,在被反序列化后,transient变量的值被设为初始值,如 int型的是
	// 0,对象型的是 null,还可以对敏感字段加密
	transient int age; 

	public Student(String name, int id, double score, int age) {
		this.name = name;
		this.id = id;
		this.score = score;
		this.age = age;
	}

	public Student() {
		System.out.println("I am a student!");
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", id=" + id + ", score=" + score
				+ "]";
	}
}

输出结果:

通过实现Externalizable实现自定义序列化:

// Student类实现Externalizable接口实现自定义序列化
class Student implements Externalizable {

	private static final long serialVersionUID = -5139397063007446571L;

	String name;
	int id;
	double score;
        // 可以阻止该变量被序列化到文件中,在被反序列化后,transient变量的值被设为初始值,如 int型的是
	// 0,对象型的是 null,还可以对敏感字段加密
	transient int age;

	public Student(String name, int id, double score, int age) {
		this.name = name;
		this.id = id;
		this.score = score;
		this.age = age;
	}

	public Student() {
		System.out.println("I am a student!");
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", id=" + id + ", score=" + score
				+ "]";
	}

	@Override
	public void writeExternal(ObjectOutput out) throws IOException {
		out.writeUTF(name);
		out.writeInt(id);
		out.writeDouble(score * 0.75);
	}

	@Override
	public void readExternal(ObjectInput in) throws IOException,
			ClassNotFoundException {
		name = in.readUTF();
		id = in.readInt();
		score = in.readDouble();
	}
}

运行结果:

对比默认序列化与自定义序列化我们可以发现:

1.写入后文件大小发生改变,自定义序列化写入的文件大小小于默认序列化的大小,即为序列化规则发生改变;

2.自定义序列化中,我们可以对属性自定义规则;

3.根据输出结果来看,自定义序列化通过无参构造方法创建对象,而默认序列化不是,所以如果想实现自定义序列化则必须要有空构造函数。

猜你喜欢

转载自blog.csdn.net/hm_135/article/details/105035357