1.Serializable接口
只是一个表识接口,仅仅是告诉jvm这是一个可以序列化的接口。
2.serialVersionUID
只要这个UID的值不变,在序列化的版本中增加属性或者减少属性就不会报错;否则当版本变更后,再反序列会报错;
如果自己不定义,每次在编译的时候,编译器会自动生成一个值,但是不能保证每次编译时的值都一样,所以务必自己定义!
3.readResolve、readObject、writeReplace、writeObject接口
public class FooImpl implements java.io.Serializable{
private String message;
public String getFoo() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
System.out.println("writeObject invoked");
out.writeObject(this.message == null ? "hohohahaha" : this.message);
}
private void readObject(java.io.ObjectInputStream in) throws IOException,
ClassNotFoundException {
System.out.println("readObject invoked");
this.message = (String) in.readObject();
}
private Object writeReplace() throws ObjectStreamException {
System.out.println("writeReplace invoked");
return this;
}
private Object readResolve() throws ObjectStreamException {
System.out.println("readResolve invoked");
return this;
}
public Object serialize() throws IOException, ClassNotFoundException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(this);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}
public static void main(String[] args) throws IOException,
ClassNotFoundException {
FooImpl fooimpl = new FooImpl();
fooimpl.serialize();
}
}
我们运行这段代码看到的debug信息:
writeReplace invoked (序列化时调用)
writeObject invoked (序列化时调用)
readObject invoked (反序列化时调用)
readResolve invoked(反序列化时调用)
4.Externalizable
Externalizable 是一个有实际方法需要实现的interface,包括writeExternal和readExternal,是Serializable接口的子接口:
- public class FooImpl implements java.io.Externalizable {
- private String message;
- public String getFoo() {
- return message;
- }
- public void setMessage(String message) {
- this.message = message;
- }
- private Object writeReplace() throws ObjectStreamException {
- System.out.println("writeReplace invoked");
- return this;
- }
- private Object readResolve() throws ObjectStreamException {
- System.out.println("readResolve invoked");
- return this;
- }
- public Object serialize() throws IOException, ClassNotFoundException {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- ObjectOutputStream oos = new ObjectOutputStream(baos);
- oos.writeObject(this);
- ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
- ObjectInputStream ois = new ObjectInputStream(bais);
- return ois.readObject();
- }
- public void readExternal(ObjectInput arg0) throws IOException,
- ClassNotFoundException {
- System.out.println("readExternal invoked");
- Object obj = arg0.readObject();
- }
- public void writeExternal(ObjectOutput arg0) throws IOException {
- System.out.println("writeExternal invoked");
- arg0.writeObject("Hello world");
- }
- public static void main(String[] args) throws IOException,
- ClassNotFoundException {
- FooImpl fooimpl = new FooImpl();
- fooimpl.serialize();
- }
- }
我们运行这段代码看到的debug信息:
writeReplace invoked
writeExternal invoked
readExternal invoked
readResolve invoked
在此writeExternal 和readExternal 的作用与writeObject和readObject 一样.
最后,当我们同时实现了两个interface的时候,JVM只运行Externalizable 接口里面的writeExternal 和readExternal 方法对序列化内容进行处理.
需要注意的是:Serializable是一个真正的mark interface,
writeObject,readObject, writeReplace,readResolve是直接与JVM通信,告诉JVM序列化的内容.