序列化和readObject/writeObject

Java中需要序列化的类,只需实现Serializable接口,具体的实现由虚拟机负责调用相关实现方式去实现。所有的non-transient和non-static都将被序列化。

class SessionDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    private int data; // Stores session data

    // Session activation time (creation, deserialization)
    private long activationTime; 

    public SessionDTO(int data) {
        this.data = data;
        this.activationTime = System.currentTimeMillis();
    }

    public int getData() {
        return data;
    }

    public long getActivationTime() {
        return activationTime;
    }
}

public class SerializeTester implements Serializable {
    public static void main(String... strings) throws Exception {
        File file = new File("out.ser");

        ObjectOutputStream oos = new ObjectOutputStream(
            new FileOutputStream(file));
        SessionDTO dto = new SessionDTO(1);
        oos.writeObject(dto);
        oos.close();

        ObjectInputStream ois = new ObjectInputStream(
            new FileInputStream(file));
        SessionDTO dto = (SessionDTO) ois.readObject();

        System.out.println("data : " + dto.getData()
            + " activation time : " + dto.getActivationTime());
        ois.close();
    }
}

某些情况下,如果某些字段不需要进行序列化,可以将其设置为transient,这样这些字段就不会进行序列化,以减轻对网络带宽的占用。某些值,如果需要在反序列化的时候重新赋值,可以设置为transient,并且重写readObject方法,在其中为该属性赋值。如果希望序列化的时候对某些值做自定义的处理,可以重写writeObject方法,添加相应逻辑。

class SessionDTO implements Serializable {
    private static final long serialVersionUID = 1L;
    private transient int data; // Stores session data

    //Session activation time (creation, deserialization)
    private transient long activationTime; 

    public SessionDTO(int data) {
        this.data = data;
        this.activationTime = System.currentTimeMillis();
    }

    private void writeObject(ObjectOutputStream oos) throws IOException {
        oos.defaultWriteObject();
        oos.writeInt(data);
        System.out.println("session serialized");
    }

    private void readObject(ObjectInputStream ois) throws IOException,
            ClassNotFoundException {
        ois.defaultReadObject();
        data = ois.readInt();
        activationTime = System.currentTimeMillis();
        System.out.println("session deserialized");
    }

    public int getData() {
        return data;
    }

    public long getActivationTime() {
        return activationTime;
    }
}

两个方法都是private的,并且它们既不存在于java.lang.Object,也没有在Serializable中声明。那么ObjectOutputStream如何使用它们的呢?这个吗,ObjectOutputStream使用了反射来寻找是否声明了这两个方法。因为ObjectOutputStream使用getPrivateMethod,所以这些方法不得不被声明为priate以至于供ObjectOutputStream来使用。