Java序列化Serializable和Externalizable

Java的对象序列化将那些实现了Serializable接口的对象转换成一个字节序列,并可以在以后将这个字节序列完全恢复为原来的对象。

对象序列化概念的加入,为了提供对 两种主要特性的支持。

①Java的“远程方法调用”(RMI)使存活于其他计算机上的对象使用起来就像是存活在本机上一样。

②对Java Beans序列化,使用一个Bean时,一般情况下是在设计阶段对它的状态信息进行配置。这种状态信息必须保存下来,并在程序启动以后,进行恢复;具体公共由对象序列化完成。

为了序列化一个对象,首先要创建某些OutputStream对象,然后将其封装在一个ObjectOutStream对象内。这时,只需要调用writeObject()即可将对象序列化,并将其发送给Outputstream。要将一个序列重组为一个对象,需要将一个Inputstream封装在 ObjectInputstream内,然后调用readObject()。和往常一样,我们最后获得的是指向一个向上转型为Object的句柄,所以必须向下转型,以便能够直接对其进行设置。

对象序列化不仅保存了对象的“全景图”,而且能够追踪对象内包含的所有引用并保存那些对象;接着又能对每个这样的对象内包含的引用进行追踪。

例子:

public class Worm implements Serializable{
private static Random rand = new Random();
private Data[] datas={
new Data(rand.nextInt(10)),
new Data(rand.nextInt(10)),
new Data(rand.nextInt(10))
};
private Worm next;
private char c;
public Worm(int i,char x){
System.out.println("Worm constructor:"+i);
c=x;
if(--i>0){
next = new Worm(i, (char)(x+1));
}
}
public Worm(){
System.out.println("Default constructor");
}
public String toString(){
String string =":"+c+"(";
for(int i = 0;i<datas.length;i++)
string+=datas[i];
string+=")";
if(next!=null)
string+=next;
return string;
}
public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
Worm worm = new Worm(6,'a');
System.out.println("worm="+worm);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("worm.out"));
out.writeObject("Worm storage\n");
out.writeObject(worm);
out.close();
ObjectInputStream in = new ObjectInputStream(new FileInputStream("worm.out"));
String string = (String)in.readObject();
Worm worm2 = (Worm)in.readObject();
System.out.println(string+"worm2="+worm2);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
ObjectOutputStream out2 = new ObjectOutputStream(bout);
out2.writeObject("Worm storage\n");
out2.writeObject(worm);
out2.flush();
ObjectInputStream in2 = new ObjectInputStream(new ByteArrayInputStream(bout.toByteArray()));
string = (String)in2.readObject();
Worm worm3 =(Worm)in2.readObject();
System.out.println(string+"worm3="+worm3);
Scanner scanner = new Scanner(System.in);
}


}
class Data implements Serializable{
private int n;
public Data(int n){
this.n = n;
}
public String toString(){
return Integer.toString(n);
}
}

输出结果:

Worm constructor:6
Worm constructor:5
Worm constructor:4
Worm constructor:3
Worm constructor:2
Worm constructor:1
worm=:a(303):b(425):c(161):d(404):e(370):f(198)
Worm storage
worm2=:a(303):b(425):c(161):d(404):e(370):f(198)
Worm storage
worm3=:a(303):b(425):c(161):d(404):e(370):f(198)

transient关键字:如果我们正在操作的是一个Serializable对象,那么所有序列化操作都会自动进行。为了能够于以控制,可以用transient(瞬时)关键字逐个域地关闭序列化。

Externalizable

除了transient关键字我们还可以通过实现Externalizable接口进行控制。

Externalizable接口代替实现了Serializable接口来对序列化过程进行控制。这个Externalizable接口继承了Serializable接口,同时增添了两个方法:writeExternal()和readExternal()。

用例:

class Blip1 implements Externalizable{
private String name;
private String password;
public Blip1(String name,String password){
System.out.println("Blip Constructor");
this.name = name;
this.password = password;
}
public Blip1(){
System.out.println("Blip Constructor");
}
public void writeExternal(ObjectOutput out) throws IOException{
System.out.println("Blip1.writeExternal");
out.writeObject(this.name);
//out.writeObject(this.password);
}
public void readExternal(ObjectInput in) throws ClassNotFoundException, IOException{
System.out.println("Blip1.readExternal");
this.name = (String)in.readObject();
//this.password = (String)in.readObject();
}
public String toString(){
return "name:"+this.name+" password:"+this.password;
}
}
class Blip2 implements Externalizable{

Blip2(){
System.out.println("Blip Constructor");
}
public void writeExternal(ObjectOutput out){
System.out.println("Blip2.writeExternal");
}
public void readExternal(ObjectInput in){
System.out.println("Blip2.readExternal");
}
}
public class Blips {


public static void main(String[] args) throws IOException, ClassNotFoundException {
// TODO Auto-generated method stub
System.out.println("Constructing objects:");
Blip1 blip1 = new Blip1("zhangsan","123456");
System.out.println(blip1.toString());
Blip2 blip2 = new Blip2();
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("Blips.out"));
System.out.println("Sava objects:");
out.writeObject(blip1);
out.writeObject(blip2);
ObjectInputStream in = new ObjectInputStream(new FileInputStream("Blips.out"));
System.out.println("Recovering b1:");
blip1 = (Blip1)in.readObject();
System.out.println(blip1.toString());
//Throw an Exception
/* System.out.println("Recovering b2:");
blip2 = (Blip2)in.readObject();*/

}


}

结果:

Constructing objects:
Blip Constructor
name:zhangsan password:123456
Blip Constructor
Sava objects:
Blip1.writeExternal
Blip2.writeExternal
Recovering b1:
Blip Constructor
Blip1.readExternal
name:zhangsan password:null

注意:例子中没有恢复Blip2对象,那样会导致一个异常,因为Blip2的构造方法不是公共的。

Externalizable对象,所有普通的缺省构造器都会被调用(包括定义时的初始化),然后调用readExternal()。

我们不仅需要在writeExternal()方法中将来自对象的重要信息写入,还必须在readExternal()方法中恢复数据。

假如不再readExternal()中初始化,将会为null,以Blip的password为例。

如果我们不是特别想要实现Externalizable接口,我们可以实现Serializable接口,并添加(不是重载或实现)名为writeObject()和readObject()方法。这样一旦对象被序列化或反序列化就会自动调用这两个方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值