疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

关于Java序列化的一些高级用法


 

   该说的都在注释中说完了。直接给程序吧。

  [java] view plaincopyprint?

  package test.javaPuzzler.p5;

  import java.io.*;

  import java.io.ObjectInputStream.GetField;

  import java.io.ObjectOutputStream.PutField;

  // 转载请注明来自http://blog.csdn.net/sunxing007

  // 一个类实现Serializable来表明自己可以被序列化;

  // 有一点需要特别注意的是:

  // 如果子类实现了Serializable,而父类没有,则父类不会被序列化;

  public class SerializableObject implements Serializable {

  // 生成的序列化版本号会因为编译环境,声明的类名,成员名称和数量的变化而不同;

  // 也就是说这个版本号一定程度上记录着类的定义性的信息,如果类的定义变化了,最好重新生成版本号;

  // 如果新的代码使用了旧的版本号,则在反序列化的时候,可以兼容读取旧类的字节码而不会报错;

  private static final long serialVersionUID = 9038542591452547920L;

  public String name;

  public String password;

  // 如果你不希望某个非静态成员被序列化,可以用transient来修饰它;

  public transient int age;

  // 静态成员不会被序列化,因为序列化保存的是实例的状态信息,而静态成员是类的状态信息;

  public static int version = 1;

  public SerializableObject(String name, String password) {

  this.name = name;

  this.password = password;

  }

  // 每个类可以写一个writeObject方法,这个方法将会负责该类自身的序列化过程;

  // 比如对于敏感信息如password,可以加密之后再序列化;

  // 这个过程需要用到PutField,它可以指定哪些域会被序列化,怎么序列化(比如加密);

  // 如果没有定义这个方法,将会调用ObjectOutputStream 的 defaultWriteObject;

  // 你可以注释掉readObject方法,然后运行测试用例来测试密码是否被加密;

  private void writeObject(ObjectOutputStream out) throws IOException {

  PutField putFields = out.putFields();

  putFields.put("name", name);

  // 模拟加密密码

  putFields.put("password", "thePassword:" + password);

  out.writeFields();

  }

  // 每个类可以写一个readObject方法,该方法负责该类自身的反序列化过程;

  // 比如对序列化时加密后的密码解密;

  // 这个过程需要用到GetField,他可以具体地读取每个域;或执行解密动作等等;

  // 如果没有定义这个方法,将会调用ObjectInputStream 的 defaultReadObject;

  private void readObject(ObjectInputStream in)

  throws ClassNotFoundException, IOException {

  GetField readFields = in.readFields();

  // 读取到成员的值之后,直接赋给该域,即完成该域的反序列化;

  name = (String) readFields.get("name", "defaultName");

  // 模拟解密密码

  String encPassword = (String) readFields.get("password",

  "thePassword:defaultValue");

  password = encPassword.split(":")[1];

  }

  // 序列化

  // 主要用到ObjectOutputStream;

  public void save() throws IOException {

  FileOutputStream fout = new FileOutputStream("e:obj");

  ObjectOutputStream oout = new ObjectOutputStream(fout);

  oout.writeObject(this);

  oout.close();

  fout.close();

  }

  // 反序列化

  // 主要用到ObjectInputStream

  public static SerializableObject load() throws IOException,

  ClassNotFoundException {

  FileInputStream fin = new FileInputStream("e:obj");

  ObjectInputStream oin = new ObjectInputStream(fin);

  Object o = oin.readObject();

  return (SerializableObject) o;

  }

  @Override

  public String toString() {

  return "name: " + name + ", password: " + password;

  }

  // 测试用例

  public static void main(String[] args) throws IOException,

  ClassNotFoundException {

  SerializableObject so = new SerializableObject(

  "http://blog.csdn.net/sunxing007", "123456");

  so.save();

  System.out.println(so);

  System.out.println(SerializableObject.load());

  }

  }