序列化:把对象转换为字节序列的过程称为对象的序列化。通过实现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.根据输出结果来看,自定义序列化通过无参构造方法创建对象,而默认序列化不是,所以如果想实现自定义序列化则必须要有空构造函数。