java序列化Serializable跟Externalizable

java序列化Serializable和Externalizable
Serializable是二进制位为基础保存的,可以没有任何构造方法。
Externalizable必须要手动提供一个public no-arg构造方法,否则会报错!
transient表示变量不被序列化,但是如果一个类实现Externalizable在writeObject()仍然把transient变量序列了,是可以成功的。这就失去了transient的意义!

实现Serializable也可以自定义序列化。
要有
private void writeObject(ObjectOutputStream stream) throws IOException;

private void readObject(ObjectInputStream stream)throws IOException, ClassNotFoundException

这两个方法,其中这两个方法分别是在ObjectOutputStream和ObjectInputStream中被调用,且是同名方法,在ObjectOutputStream和ObjectInputStream中还有defaultWriteObject和defaultReadObject两个方法用于对非transient变量的序列化与反序列化。

还有一种特殊的情况:序列化单例和类型安全的枚举。

在jdk5.0以前,Enum还未出现,这时一个类中会有私有构造方法来创建多个枚举值,如下

public class Orientation implements Serializable{
  private int value ;
  private Orientation(int i){
    value = i;
   }

   public static final Orientation HORIZONTAL = new Orientation(1);
   public static final Orignetation VERTICAL = new Orientation(2);
}

构造器是私有的,那么在这个类外就不可能会出现除HORIZONTAL和 VERTICAL的其它枚举值,因此可以用==来进行比较 ,但是在序列化和反序列化(即使构造器是私有的也可以反序列化),那么反序列化后的value和原先的HORIZONTAL和VERTICAL不能再用==比较了,因此这里就会有问题。
这时就需要再用一个方法  protected Object readResolve() throws ObjectStreamException{
   if(value == 1){
        return Orientation.HORIZONTAL;
    }
    if(value == 2){
        return Orientation.VERTICAL;
     }
     return null;// this should not happen
}

在readObject()后面调用,将反序列化后的对象用另一个对象替换。还有一个writeReplace()方法是在writeObject()前调用,将一个对象替换成另一个对象进行序列化。