【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
谨慎地实现Serializable
实现Serializable有以下几点风险
- 实现Serializable的类一旦发布,则“改变这个类的实现”的灵活性将大大降低。
- 增加了错误和安全漏洞的可能性。
- 测试负担会增加。
为了继承而设计的类应该很少实现Serializable,接口也应该很少会扩展它。
保护性地编写readObject方法
不严格的说,readObject是一个“用字节流作为唯一参数”的构造函数"。所以在写readObject时,就想象自己正在编写一个构造函数。
例如,在一个类的构造函数中,对参数的有效性做了检查,并且也做了保护性拷贝的话,readObject中也应该实现该逻辑。Period类(参考
http://my.oschina.net/u/1453800/blog/263037#OSC_h3_2)的readObject可以写成这样:
private void readObject(ObjectInputStream s) throws IOException,
ClassNotFoundException {
s.defaultReadObject();
start = new Date(start.getTime());
end = new Date(end.getTime());
if (start.compareTo(end) > 0) {
throw new InvalidObjectException(start + "after" + end);
}
}
值得注意的是,这样实现后,start和end都不能再定义成final了。不过下文会介绍readResolve方法,可以作为保护性readObject的替代选择,并且保证start和end还能继续定义成final。
在readObject中,无论是直接方式还是间接方式,都不要调用类中可被改写的方法。
必要时提供一个readResolve方法
readResolve有两个用法:
- 用来实现singletor的序列化
- 作为保护性的readObject方法的一种保守替代选择,它的好处有:减少代码冗余,也不需要考虑太多细节;消除了“序列化对于使用final域的人为限制”。
Peroid类的readResolve方法实现如下:
private Object readResolve() throws ObjectStreamException {
return new Period(start, end);
}
来源:oschina
链接:https://my.oschina.net/u/1453800/blog/263353