在实际应用中,我们有时需要将对象保存到磁盘文件或者网络中,保存对象的过程实质上就是对象序列化(即把对象转换为字节序列的过程称为对象的序列化)的过程。
相应的,把字节序列恢复为对象的过程称为对象的反序列化。
我们通过对象的序列化来把对象的字节序列永久地保存到硬盘上(通常存放在一个文件中)或者在网络上传送对象的字节序列。
对于对象的序列化来说,只需要将被序列化的类实现Serializable接口就可以进行对象的序列化操作。
注意:
Serializable接口中没有任何方法,让一个类实现该接口只是为了标注该对象是可以被序列化的。序列化只能保存对象的实例变量,但不能保存类的任何方法和类变量,并且保存的只是变量的值,对于变量的任何修饰符都不能保存。对于某些类型的对象,其状态是瞬时的,这样的对象是无法保存其状态的,如线程对象或流对象。对于这样的成员变量,必须用transient关键字标明,否则编译器将报错。即任何用transient关键字标明的成员变量在序列化时都不会被保存。
如下为User类对象序列化的例子import java.io.Serializable;
class User implements Serializable {
/**
* 序列化版本号
*/
private static final long serialVersionUID = 4658610475461707938L;
String name;
transient int age;
public User(String name,int age) {
this.name=name;
this.age=age;
}
public String toString() {
return "名字:"+name+"年龄:"+age;
}
}
其中序列化版本号用于反序列化时控制字段方法增减,即当序列化版本号相同时对User字段方法进行改动后接着反序列化改动前的文件仍然可以反序列化成功,反之如果不对序列化版本号进行显示声明时当反序列化改动前的文件时程序会报错。
将一个对象序列化后,可以使用对象输出/输入流将其联系起来,通过对象输出流将对象状态保存下来(即将对象保存到文件中,或者通过网络传送到其他地方),通过对象输入流将对象状态恢复。
在java中提供了ObjectInputStream类和ObjectOutputStream类分别实现了接口ObjectInput和ObjectOutput。其中ObjectOutput接口用writeObject()方法可以直接将对象保存到输出流中,而ObjectInput接口使用readObject()方法可以直接从输入流中读取一个对象。
对象流的构造方法以及方法与数据流的构造方法以及方法基本相同,这里不再赘述。
下面举一个例子,此例中使用对象为上文User类实例对象,将一个实例化后的User对象通过序列化储存进文件中,再通过反序列化进行读取并打印到控制台。
代码如下:import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class HelloWorld {
public static void main(String[] args) {
// 对流进行声明,实例化User对象
FileOutputStream fos = null;
FileInputStream fis = null;
ObjectOutputStream oos = null;
ObjectInputStream ois = null;
User u = new User("张三", 12);
User temp = null;
// try-catch进行异常处理
try {
// 声明一个文件"d://test.txt",并且使用FileOutputStream作为节点流打开
fos = new FileOutputStream("d://test.txt");
// 将fos作为对象输出流的节点流并连接
oos = new ObjectOutputStream(fos);
// 将User的实例u写入到test.txt
oos.writeObject(u);
// 关闭流
oos.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
// 使用输入流来读取文件中的一个对象并在控制台输出
fis = new FileInputStream("d://test.txt");
ois = new ObjectInputStream(fis);
temp = (User) ois.readObject();
System.out.println(temp.toString());
// 关闭流
ois.close();
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行后可以在d盘中查看test文件,其中内容如下:
接着控制台会输出如下内容: