1.序列化和反序列化
将对象转换为字节流保存起来,并在以后还原这个对象,这种机制叫做对象序列化。将一个对象保存到永久存储设备上称为持久化。一个对象要想能够实现序列化,必须实现java.io.Serializable接口。该接口中没有定义任何方法,是一个标识性接口(Marker Interface),当一个类实现了该接口,就表示这个类的对象是可以序列化的。序列化(serialization)是把一个对象的状态写入一个字节流的过程。当你想要把你的程序状态存到一个固定的存储区域,例如文件时,它是很管用的。
从程序到外面叫序列化,从外面读回来叫反序列化。
2.序列化特点
假设一个被序列化的对象引用了其他对象,同样,其他对象又引用了更多的对象。这一系列的对象和它们的关系形成了一个顺序图表。
对象序列化和反序列化工具被设计出来并在这一假定条件下运行良好。
如果你试图序列化一个对象图表中顶层的对象,所有其他的引用对象都被循环地定位和序列化;同样,在反序列化过程中,所有的这些对象以及它们的引用都被正确地恢复。
3.序列化实现细节
只有实现Serializable接口的对象可以被序列化工具存储和恢复。Serializable接口没有定义任何成员,它只用来表示一个类可以被序列化。
如果一个类可以被序列化,它的所有子类都可以序列化。
当一个对象被序列化时,只保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量。
如果一个对象的成员变量是一个对象,那么这个对象的数据成员也会被保存。
如果一个可序列化的对象包含对某个不可序列化对象的引用,那么整个序列化操作将会失败,并且会抛出一个NotSerializableException。
我们可以将这个不可序列化的引用标记为transient,那么原对象仍然可以序列化。使用transient修饰的变量将不会被序列化。
反序列化时不会调用对象的任何构造方法,仅仅根据所保存的对象状态信息,在内存中重新构建对象。
4.实现代码
重点:需要序列化的对象必须实现Serializable接口
需要序列化的对象(实体类)
public class User implements Serializable {
private String name;
private String password;
private int age;
public User(String name, String password, int age) {
this.name = name;
this.password = password;
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", password=" + password + ", age=" + age + "]";
}
}
//使用对象流来实现序列化和反序列化
public class ObjectInputStreamAndObjectOutputStreamDemo {
private static File file;
public static void main(String[] args) throws Exception {
file=new File("file/obj.txt");
writerObject();
readerObject();
}
//反序列化操作
private static void readerObject() throws Exception{
ObjectInputStream in =new ObjectInputStream(new FileInputStream(file));
Object content=in.readObject();
System.out.println(content);
in.close();
}
//序列化操作
private static void writerObject() throws Exception {
ObjectOutputStream out=new ObjectOutputStream(new FileOutputStream(file));
out.writeObject(new User("张三","123456",17));
out.close();
}
}