扔个三星炸死你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。且在序列化对象时,不仅会序列化当前对象本身,还会对该对象引用的其它对象也进行序列化。