Java 对象序列化

    Java 对象序列化主要用到了下面两个类:
    ObjectOutputStream
    ObjectInputStream
    Java 提供了了默认的自动对象序列化机制,只需要实现Serializable接口就可以了。Serializable是一个空接口,里面没有任何方法。下面简单的看一个例子:
        import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Demo implements Serializable{
 private static final long serialVersionUID = 1L;
 String s;
 public Demo(String str){
  s = str;
 }
 public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
  String name = "Demo.out";
  ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(name));
  Demo d = new Demo("Demo");
  System.out.println("1:"+d.s);
  oos.writeObject(d);
 
  ObjectInputStream ois = new ObjectInputStream(new FileInputStream(name));
  Demo demo = (Demo) ois.readObject();
  System.out.println("2:"+d.s);
 }
}
    程序运行结果为:
     1:Demo
    2:Demo
    正如大家所看到的默认的对象序列化机制相当简单。Java同时还提供了另外一种机制,可以手动来对序列化过程进行控制。
    这种方法需要实现Externalizable接口。
public interface Externalizable extends java.io.Serializable {
    void writeExternal(ObjectOutput out) throws IOException;
    void readExternal(ObjectInput in) throws IOException, ClassNotFoundException;
}
    Externalizable接口继承于Serializable接口,同时增加了两个方法writeExternal()和readExternal()。这两个方法会在对象的序列化和反序列化的过程中被自动调用,以便执行一些特殊操作。
        import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
class Blip1 implements Externalizable {
 public Blip1() {
  Blip.print("Blip1 Construct");
 }
 @Override
 public void writeExternal(ObjectOutput out) throws IOException {
  Blip.print("Blip1 writeExternal");
 }
 @Override
 public void readExternal(ObjectInput in) throws IOException,
   ClassNotFoundException {
  Blip.print("Blip2 readExternal");
 }
}
class Blip2 implements Externalizable {
 Blip2() {
  Blip.print("Blip2 Construct");
 }
 @Override
 public void writeExternal(ObjectOutput out) throws IOException {
  Blip.print("Blip2 writeExternal");
 }
 @Override
 public void readExternal(ObjectInput in) throws IOException,
   ClassNotFoundException {
  Blip.print("Blip2 readExternal");
 }
 
}
public class Blip{
 static void print(String s) {
  System.out.println(s);
 }
 public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
  print("Constructing objects");
  Blip1 b1 = new Blip1();
  Blip2 b2 = new Blip2();
  print(b1+":"+b2);
  String file = "Blip.out";
  ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file ));
  print("Saving object");
  out.writeObject(b1);
  out.writeObject(b2);
  out.close();
 
  ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
  print("Recovering b1:");
  b1 = (Blip1) in.readObject();
  print("Recovering b2:");
  b2 = (Blip2) in.readObject();
 
  print(b1+":"+b2);
 }
}
这段代码的运行结果为:
Constructing objects
Blip1 Construct
Blip2 Construct
com.leo.io.Blip1@1fb8ee3:com.leo.io.Blip2@61de33
Saving object
Blip1 writeExternal
Blip2 writeExternal
Recovering b1:
Blip1 Construct
Blip2 readExternal
Recovering b2:
Exception in thread "main" java.io.InvalidClassException: com.leo.io.Blip2; com.leo.io.Blip2; no valid constructor
 at java.io.ObjectStreamClass.checkDeserialize(Unknown Source)
 at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
 at java.io.ObjectInputStream.readObject0(Unknown Source)
 at java.io.ObjectInputStream.readObject(Unknown Source)
 at com.leo.io.Blip.main(Blip.java:72)
Caused by: java.io.InvalidClassException: com.leo.io.Blip2; no valid constructor
 at java.io.ObjectStreamClass.<init>(Unknown Source)
 at java.io.ObjectStreamClass.lookup(Unknown Source)
 at java.io.ObjectOutputStream.writeObject0(Unknown Source)
 at java.io.ObjectOutputStream.writeObject(Unknown Source)
 at com.leo.io.Blip.main(Blip.java:65)
 
为什么会报错呢?大家仔细看代码会发现
Blip1 和 Blip2 的默认构造函数有所区别,把Blip2的构造函数改为:
public Blip2() {
  Blip.print("Blip2 Construct");
 }
然后运行,结果为:
Constructing objects
Blip1 Construct
Blip2 Construct
com.leo.io.Blip1@1fb8ee3:com.leo.io.Blip2@61de33
Saving object
Blip1 writeExternal
Blip2 writeExternal
Recovering b1:
Blip1 Construct
Blip2 readExternal
Recovering b2:
Blip2 Construct
Blip2 readExternal
com.leo.io.Blip1@69b332:com.leo.io.Blip2@173a10f

    由此我们可以看出:对于Serializable对象,对象完全以它存储的二进制位为基础来构造。而不调用构造器;对于Externalizable 对象,默认构造器在readExternal()里会被调用。所以Externalizable 必须提供一个默认构造器。一般都是在writeExternal()里将需要的信息写入,在readExternal()恢复数据。
     下面的这个例子示范了如何完整保存和恢复一个Externalizable 对象
        import java.io.Externalizable;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
public class Blip3 implements Externalizable {
 private int i;
 private String s;
 public Blip3(){
  print("Blip3 default construct");
 }
 
  public Blip3(String x, int a){
  print("Blip3(String "+ x+ ", int" + a +")");
  s = x;
  i = a;
 }
 
 
 @Override
 public String toString() {
  return s + i;
 }
 static void print(String s) {
  System.out.println(s);
 }
 
 
 @Override
 public void writeExternal(ObjectOutput out) throws IOException {
  print("Blip3 writeExternal");
  out.writeObject(s);
  out.writeInt(i);
 }
 @Override
 public void readExternal(ObjectInput in) throws IOException,
   ClassNotFoundException {
  print("Blip3 readExternal");
  s = (String) in.readObject();
  i = in.readInt();
 }
 public static void main(String[] args) throws FileNotFoundException, IOException, ClassNotFoundException {
  Blip3 b3 = new Blip3("A", 47);
  print(b3.toString());
 
  String name = "Blip3.out";
  ObjectOutputStream o = new ObjectOutputStream(new FileOutputStream(name));
  o.writeObject(b3);
  o.close();
 
  ObjectInputStream in = new ObjectInputStream(new FileInputStream(name));
  b3 = (Blip3) in.readObject();
  print(b3.toString());
 }
}
运行结果:
Blip3(String A, int47)
A47
Blip3 writeExternal
Blip3 default construct
Blip3 readExternal
A47
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值