序列化
对象要想序列化,需要类实现接口 Serializable与Externalizable其中之一
Seializable
类通过实现 java.io.Serializable 接口以启用其序列化功能。未实现此接口的类将无法使其任何状态序列化或反序列化。
可序列化类的所有子类型本身都是可序列化的。序列化接口没有方法或字段,仅用于标识可序列化的语义。
如果实现Serializable接口,对象如何序列化,各个属性序列化的顺序是什么,都是默认的,程序员无法指定,也不用关心。
如果属性前面有static和transient修饰,不参与序列化。
Externalizable
Externalizable接口继承自Serializable,但是增加了两个方法即writeExternal方法和readExternal方法
在writeExternal方法中,自定定制哪些属性要序列化,顺序是什么样。
在readExternal方法中,自定定制哪些属性要反序列化,顺序和writeExternal的方法中一致。
先说实现Serializable接口的类对象反序列化时是否需要空参构造。
查找ObjectStreamClass源码 找到一个方法
private static Constructor> getSerializableConstructor(Class>cl) {
Class> initCl =cl;while (Serializable.class.isAssignableFrom(initCl)) {if ((initCl = initCl.getSuperclass()) == null) {return null;
}
}try{
Constructor> cons = initCl.getDeclaredConstructor((Class>[]) null);int mods =cons.getModifiers();if ((mods & Modifier.PRIVATE) != 0 ||((mods& (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 &&
!packageEquals(cl, initCl)))
{return null;
}
cons=reflFactory.newConstructorForSerialization(cl, cons);
cons.setAccessible(true);returncons;
}catch(NoSuchMethodException ex) {return null;
}
}
方法注释为:
Returns subclass-accessible no-arg constructor of first non-serializable superclass, or null if none found. Access checks are disabled on the returned constructor (if any)。
即:该方法会返回Serializable接口实现类往上一直寻找到第一个没有实现该接口父类的空参构造方法,若第一个没有实现该接口的父类没有空参构造方法,则会抛出java.io.InvalidClassException: IO.goods; no valid constructor异常,如果该实现类有无空参构造都可以,但是第一个没有实现该接口的父类必须有
实现Externalizable接口的类对象反序列化时是否需要空参构造。
同样的,查找ObjectStreamClass源码发现,
private static Constructor> getExternalizableConstructor(Class>cl) {try{
Constructor> cons = cl.getDeclaredConstructor((Class>[]) null);
cons.setAccessible(true);return ((cons.getModifiers() & Modifier.PUBLIC) != 0) ?cons :null;
}catch(NoSuchMethodException ex) {return null;
}
}
该方法注释为:
Returns public no-arg constructor of given class, or null ifnone found.* Access checks are disabled on the returned constructor (ifany), since* the defining class may still be non-public.
即;查找实现类是否有空参构造,如果没有则返回null,
因此Externalizable接口实现类必须有空参构造方法,否则反序列化时会抛出 java.io.InvalidClassException异常。