ObjectOutputStream 将 Java 对象的基本数据类型和图形写入 OutputStream。可以使用 ObjectInputStream 读取(重构)对象。通过在流中使用文件可以实现对象的持久存储。如果流是网络套接字流,则可以在另一台主机上或另一个进程中重构对象。 其writeObject 方法用于将对象写入流中。
ObjectInputStream 对以前使用 ObjectOutputStream 写入的基本数据和对象进行反序列化。其readObject方法用于从流读取对象。应该使用 Java 的安全强制转换来获取所需的类型。
一旦某个类实现了Serializable接口,则该类的对象就是可序列化的,程序可以通过如下两个步骤来序列化该对象。
1)创建一个ObjectOutputStream,这个输出流是一个处理流,所以必须建立在其他节点流的基础上。
2)调用ObjectOutputStream对象的writeObject方法输出可序列化对象。
下面程序定义了一个Person类,这个Person类就是一个普通Java类,只是实现了Serializable接口。
public class Person implements Serializable{
//属性
private String name;
private int age;
//构造器
Person(){}
Person(String name, int age){
this.name = name;
this.age = age;
}
//setter和getter方法
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;
}
}
下面程序使用ObjectOutputStream将一个Person对象写入磁盘文件。
public class WriteObject {
public static void main(String[] args) {
ObjectOutputStream oos = null;
try{
//创建一个ObjectOutputStream输出流
oos = new ObjectOutputStream(new FileOutputStream("e:\\object.txt"));
Person p = new Person("郭靖", 24);
//将对象写入输出流
oos.writeObject(p);
}catch(IOException e){
e.printStackTrace();
}finally{
try{
if(oos != null)
oos.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
运行看到生产一个Person.txt文件,该文件内容就是Person对象。
如果要从二进制流中恢复Java对象,则需要使用反序列化。反序列化的步骤如下:
1)创建一个ObjectInputStream,这个输入流是一个处理流,所以必须建立在其他节点流的基础上。
2)调用ObjectInputStream对象的readObject方法读取流中的对象,该方法返回值是Object类型,一般要进行强制类型转换。
public class ReadObject {
public static void main(String[] args) {
ObjectInputStream ois = null;
try{
//创建一个ObjectInputStream输入流
ois = new ObjectInputStream(new FileInputStream("e:\\object.txt"));
//从输入流中读取一个Java对象,并将其强制转换成Person类
Person p = (Person)ois.readObject();
System.out.println("名字是:" + p.getName() + ",年龄:" + p.getAge());
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(ois != null)
ois.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
注意:
1)反序列化读取的仅仅是Java对象的数据,而不是Java类。因此采用反序列化恢复Java对象时,必须提供Java对象所属类的class文件,否则将会引发ClassNotFoundException。
2)反序列化机制无须通过构造器来初始化Java对象。
3)如果向文件中使用序列化机制写入了多个Java对象,使用反序列化机制恢复对象时必须按实际写入的顺序读取。
4)如果一个可序列化类有多个父类(包括直接或间接父类),则该类的所有父类要么是可序列化的,要么有无参数的构造器——否则会引发InvalidClassException异常。
因为当程序创建子类实例时,系统会隐式地为它的所有父类都创建实例(并建立和此子类实例的关联),当反序列化某个子类的实例时,反序列化机制需要恢复其关联的父类实例,恢复这些父类实例有两种方式:
a.使用反序列化机制。
b.使用父类无参数的构造器。
反序列化机制优先采用第一种机制。如果某个父类既不可序列化,则不能使用第一种机制;有没有提供无参数的构造器,则不可采用第二种机制,那么反序列化该子类实例时将抛出异常。