==============2015/8/27==================================
- 对象序列化
对象序列化主要是为了能够将对象实现轻量级持久性。“持久性”意味这一个对象的生存周期并不取决于程序是否正在执行,它可以生存于程序的调用之间。通过将一个序列化对象写入磁盘,然后再重新调用程序时恢复该对象,就能够实现持久性的效果。之所以称其为“轻量级”,是因为不能用某种“persistent”关键字来简单地定义一个对象,并让系统自动维护其他细节问题。相反,对象必须在程序中显示地序列化和反序列化还原。
Java的对象序列化将那些实现了Serializable接口的对象转换成一个字节序列,并能够在以后将这个字节序列完全恢复为原来的对象。这一过程甚至可用过网络进行;这意味着序列化机制能够自动弥补不同操作系统之间的差异。
对象序列化的概念加入语言中是为了支持两种主要特性。一是Java的远程方法调用(Remote Method Invocation, RMI),它使存活于其他计算机上的对象使用起来就像是存活在本机上一样。二是,对Java Beans来说,对象的序列化也是必要的。使用一个Bean时,一般情况下是在设计阶段对它的状态信息进行配置。这种状态信息必须保存下来,并在程序启动时进行后期恢复。
要序列化一个对象,首先要创建某些OutputStream对象,然后将其封装在一个ObjectOutputStream对象内。这时,只需调用writeObject()即可将对象序列化,并将其发送给OutputStream。
要反向进行该过程,需要将一个InputStream封装在ObjectInputStream内,然后调用readObject()。我们最终获得的是一个引用,它指向一个向上转型的object,所以需要向下转型才能直接设置它们。
// 读写的是文件
ObjectOutputStream out = new
ObjectOutputStream(new FileOutputStream("worm.out"));
out.writeObject("Worm
storage\n");
out.writeObject(w);
out.close(); // Also flushes output
ObjectInputStream in = new
ObjectInputStream(new FileInputStream("worm.out"));
String s = (String)in.readObject();
Worm w2 = (Worm)in.readObject();
print(s+"w2 = "+w2);
//读写的是字节数组
ByteArrayOutputStream bout = new
ByteArrayOutputStream();
ObjectOutputStream out2 = new
ObjectOutputStream(bout);
out2.writeObject("Worm
storage\n");
out2.writeObject(w);
out2.flush();
ObjectInputStream in2 = new
ObjectInputStream(new ByteArrayInputStream(bout.toByteArray()));
s = (String)in2.readObject();
Worm w3 = (Worm)in2.readObject();
print(s+"w3 = "+w3);
|
1.
一旦从另外某个流创建了ObjectOutputStream,writeObject()就会将对象序列化。也可以为一个String调用一个writeObject()。也可以用与DataOutputStream相同的方法写入所有基本数据类型(它们具有相同的接口)。
2.
这两段看起来相似的独立的代码。一个读写的是文件,而另一个读写的是字节数组(ByteArray)。
序列化的控制
对于特殊需求的序列化(比如说考虑特殊的安全而难题,或者说你不希望对象的某一部分被序列化),可通过实现Externalizable接口——代替实现Serializable接口来对序列化过程进行控制。Externalizable接口继承了Serializable接口,同时增添了两个方法writeExternal()和readExternal()。这两个方法会在序列化和反序列化还原的过程中被自动调用,以便于执行一些特殊操作。
1.在Blips.java的例子中,Blip2的构造器不是public,而是default。这一点造成了它恢复时的异常。其原因是:在恢复对象时,会调用Blip1(Blip2)的默认构造器。
这与恢复一个Serializable对象不同。对于Serializable对象,对象完全以它存储的二进制位为基础来构造,而不调用构造器。而对于一个Externalizable对象,所有普通的默认构造器都会被调用(包括字段定义时的初始化),然后调用readExternal()。
public
class Blip3 implements Externalizable {
private int i; private String s;// No initialization
public Blip3() {
print("Blip3 Constructor");
// s, i not initialized
}
public Blip3(String x, int a) {
print("Blip3(String x, int
a)");
s = x;
i = a;
// s && i initialized only in
non-default constructor.
}
@Override
public void readExternal(ObjectInput in)
throws IOException,
ClassNotFoundException {
print("Blip3.readExternal");
// You must do this:
s = (String)in.readObject();
i = in.readInt();
}
@Override
public void writeExternal(ObjectOutput
out) throws IOException {
print("Blip3.readExternal");
out.writeObject(s);
out.writeInt(i);
}
…}
|
3.我们如果从一个Externalizable对象继承,通常需要调用基类版本的writeExternal()和readExternal()来为基类组件提供恰当的存储和恢复功能。
No comments:
Post a Comment