扔个三星炸死你2017-06-30 09:58:37
一個物件序列化時,依照Java預設的序列化規則,物件內的所有成員都要序列化,也就是說,這些Class都必須實作Serializable。
所以,你有兩種改法,一是Address實作Serializable接口,二是對Person中的address成員加上transient
標記,這樣該成員就不會被序列化進去。
typecho2017-06-30 09:58:37
如果 address 成員需要進行序列化的話,則Address類別也需要實作Serializable介面。
如果 address 成員不需要進行序列化的話,可以加上transient關鍵字,則address成員不做序列化操作,值為null。如下:
public class Person implements Serializable {
private static final long serialVersionUID = 1905122041950251207L;
private String name;
private transient Address address; // Noncompliant; Address isn't serializable
}
當然還有其他方式:
例如實作Externalizable接口,重寫readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法。
還有一個替代實作Externalizable介面方法,還是實作Serializable接口,加入writeObject(ObjectOutputStream obs)和readObject(ObjectInputStream ois)方法。
再說說為什麼Address一定要實作Serializable,或是加上transient關鍵字Person才能進行序列化?
先看看不做處理,使用 ObjectOutputStream 來持久化對象,拋出的異常
Exception in thread "main" java.io.NotSerializableException
看ObjectOutputStream源碼:
/**
* Underlying writeObject/writeUnshared implementation.
*/
private void writeObject0(Object obj, boolean unshared)
throws IOException
{
//......
// remaining cases
if (obj instanceof String) {
writeString((String) obj, unshared);
} else if (cl.isArray()) {
writeArray(obj, desc, unshared);
} else if (obj instanceof Enum) {
writeEnum((Enum<?>) obj, desc, unshared);
} else if (obj instanceof Serializable) {
writeOrdinaryObject(obj, desc, unshared);
} else {
if (extendedDebugInfo) {
throw new NotSerializableException(
cl.getName() + "\n" + debugInfoStack.toString());
} else {
throw new NotSerializableException(cl.getName());
}
}
} finally {
depth--;
bout.setBlockDataMode(oldMode);
}
}
從此可知, 如果被寫入物件型別是String、Array、Enum、Serializable,就可以進行序列化,否則會拋出NotSerializableException。且在序列化物件時,不僅會序列化目前物件本身,還會對該物件引用的其它物件也進行序列化。