序列化
對象要想序列化,需要類實現接口 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); return cons; } 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 if none found. * Access checks are disabled on the returned constructor (if any), since * the defining class may still be non-public.
即;查找實現類是否有空參構造,如果沒有則返回null,
因此Externalizable接口實現類必須有空參構造方法,否則反序列化時會拋出 java.io.InvalidClassException異常。
