序列化中的继承问题

来源:互联网 发布:uploadify java 上传 编辑:程序博客网 时间:2024/06/10 14:55


package tigers;

import java.io.*;


public class Tiger3 {
 static class Sub extends Super {
  private String name;
  public Sub(int id, int uid, String name) {
   super(id, uid);
   this.name = name;
  }
  public String toString() {
   return "Tiger3$Sub:(" + super.toString() + "," + name + ")";
  }

  private void writeObject(ObjectOutputStream oos) throws IOException {
   System.out.println("Sub.writeObject()");
   oos.defaultWriteObject();
  }
  private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   System.out.println("Sub.readObject()");
   ois.defaultReadObject();
  }
 }
 static class Super implements Serializable {
  private int id;
  private transient int uid;
  public Super(int id, int uid) {
   this.id = id;
   this.uid = uid;
  }
  private static final long serialVersionUID = 1L;
  private void writeObject(ObjectOutputStream oos) throws IOException {
   System.out.println("Super.writeObject()");
   oos.defaultWriteObject();
   oos.writeInt(uid);
  }
  private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   System.out.println("Super.readObject()");
   ois.defaultReadObject();
   uid = ois.readInt();
  }
  public String toString() {
   return "Tiger3$Super:(" + id + "," + uid + ")";
  }
 }
 public static void main(String[] args) {
  Tiger3.Super sup = new Tiger3.Super(55, 1000);
  Tiger3.Sub sub = new Tiger3.Sub(12, 100, "sub");
  try {
   ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Tiger3$Super.tmp"));
   oos.writeObject(sup);
   ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Tiger3$Super.tmp"));
   sup = (Tiger3.Super) ois.readObject();
   System.out.println(sup);
   oos = new ObjectOutputStream(new FileOutputStream("Tiger3$Sub.tmp"));
   oos.writeObject(sub);
   ois = new ObjectInputStream(new FileInputStream("Tiger3$Sub.tmp"));
   sub = (Tiger3.Sub) ois.readObject();
   System.out.println(sub);
  } catch (IOException ioe) {
   
  } catch (ClassNotFoundException cnfe) {
   
  }
 }
}

结果:

Super.writerObject()
Super.readObject()
Tiger3$Super:(55,1000)
Super.writerObject()
Sub.writeObject()

Super.readObject()
Sub.readObject()

Tiger3$Sub:(Tiger3$Super:(12,100),sub)

如果将Super和Sub中writeObject()和readObject()的修饰符改成public:

Tiger3$Super:(55,0)
Tiger3$Sub:(Tiger3$Super:(12,0),sub)

 


 

Tiger3$Super:(55,0)
Tiger3$Sub:(Tiger3$Super:(12,0),sub)

 


 

结论:

一、如果Super类包含需要序列化的primitive类型变量,应该实现writeObject()和readObject()方法,并在里面分别调用ObjectOutputStream.defaultWriteObject()和ObjectInputStream.defaultReadObject()方法。

二、writeObject()和readObject()的修饰符、返回类型、参数必须符合规定,即必须是如下格式:

private void writeObject(ObjectOutputStream o) throws...;

private void readObject(ObjectInputStream o) throws...;

否则这两个方法将不会被调用。

三、如果父类实现了Serializable接口,子类将自动得到可序列化特性。并且序列化子类时,父类的writeObject()和readObject()将得到调用。换言之,在序列化子类之前,父类将会自动被序列化。

 

/*
 * Created on 2005-2-7
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package tigers;

import java.io.*;

/**
 * @author bitan
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class Tiger4 {
 static class Super {
  private String name;
  public Super(String name) {
   this.name = name;
  }
  public String toString() {
   return "Tiger4$Super:(" + name + ")";
  }
 }
 static class Sub extends Super implements Serializable {
  private String name;
  Sub (String superName, String name) {
   super(superName);
   this.name = name;
  }
  public String toString() {
   return "Tiger4$Sub:("+ super.toString() + "," + name + ")";
  }
 }
 public static void main(String[] args) {
  Sub sub = new Sub("super","sub");
  try {
   System.out.println("序列化之前:" + sub);
   ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("Tiger4$Sub.tmp"));
   oos.writeObject(sub);
   System.out.println("序列化之后:" + sub);
   ObjectInputStream ois = new ObjectInputStream(new FileInputStream("Tiger4$Sub.tmp"));
   sub = (Sub) ois.readObject();
   System.out.println("反序列化之后:" + sub);
  } catch (IOException ioe) {
   ioe.printStackTrace();
  } catch (ClassNotFoundException cnfe) {
   cnfe.printStackTrace();
  }
 }
}

 

结果:

序列化之前:Tiger4$Sub:(Tiger4$Super:(super),sub)
序列化之后:Tiger4$Sub:(Tiger4$Super:(super),sub)

java.io.InvalidClassException: tigers.Tiger4$Sub; no valid constructor
 at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:428)
 at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:268)
 at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1029)
 at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:291)
 at tigers.Tiger4.main(Tiger4.java:41)

给Super加上无参数构造函数

public Super() {

    this.name = "default";

}

后:

 

序列化之前:Tiger4$Sub:(Tiger4$Super:(super),sub)
序列化之后:Tiger4$Sub:(Tiger4$Super:(super),sub)
反序列化之后:Tiger4$Sub:(Tiger4$Super:(default),sub)

 

现在,给Super的name字段加上Setter和Getter方法:

public void setName(String name) {
   this.name = name;
  }
  public String getName() {
   return name;
  }

并且给Sub加上writeObject()和readObject()方法:

private void writeObject(ObjectOutputStream oos) throws IOException {
   oos.defaultWriteObject();
   oos.writeObject(super.getName());
  }
  private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
   ois.defaultReadObject();
   super.setName((String) ois.readObject());
  }

结果:

序列化之前:Tiger4$Sub:(Tiger4$Super:(super),sub)
序列化之后:Tiger4$Sub:(Tiger4$Super:(super),sub)
反序列化之后:Tiger4$Sub:(Tiger4$Super:(super),sub)

 

结论:

一、当父类没有实现Serializable接口的前提下,序列化子类时父类将不会被自动序列化。而反序列化子类时,父类的无参数构造方法将会被调用。

二、如果想在序列化子类的同时也自动序列化父类中的字段,必须在子类的writeObject()和readObject()中相应实现。



 

原创粉丝点击