Effective Java 74 Implement Serializable judiciously
Disadvantage of Serializable
- A major cost of implementing Serializable is that it decreases the flexibility to change a class's implementation once it has been released.
If you accept the default serialized form, the class's private and package-private instance fields become part of its exported API, and the practice of minimizing access to fields (Item 13) loses its effectiveness as a tool for information hiding.
It is possible to change the internal representation while maintaining the original serialized form (using
ObjectOutputStream.putFields and ObjectInputStream.readFields ), but it can be difficult and leaves visible warts in the source code.
stream unique identifiers (serial version UIDs)
If you do not specify this number explicitly by declaring a static final long field named serialVersionUID , the system automatically generates it at runtime by applying a complex procedure to the class.
The automatically generated value is affected by the class's name, the names of the interfaces it implements, and all of
its public and protected members. If you fail to declare an explicit serial version UID, compatibility will be broken, resulting in an InvalidClassException at runtime.
- A second cost of implementing Serializable is that it increases the likelihood of bugs and security holes.
Objects are created using constructors; serialization is an extralinguistic mechanism for creating objects. Relying on the default deserialization mechanism can easily leave objects open to invariant corruption and illegal access (Item 76).
- A third cost of implementing Serializable is that it increases the testing burden associated with releasing a new version of a class.
When a serializable class is revised, it is important to check that it is possible to serialize an instance in the new release and deserialize it in old releases, and vice versa.
Principle
- Classes designed for inheritance (Item 17) should rarely implement Serializable, and interfaces should rarely extend it.
- If the class has invariants that would be violated if its instance fields were initialized to their default values (zero for integral types, false for boolean, and null for object reference types), you must add this readObjectNoData method to the class.
// readObjectNoData for stateful extendable serializable classes
private void readObjectNoData() throws InvalidObjectException {
throw new InvalidObjectException("Stream data required");
}
You should consider providing a parameterless constructor on nonserializable classes designed for inheritance .
// Nonserializable stateful class allowing serializable subclass
public abstract class AbstractFoo {
private int x, y; // Our state
// This enum and field are used to track initialization
private enum State { NEW, INITIALIZING, INITIALIZED };
private final AtomicReference<State> init = new AtomicReference<State>(State.NEW);
public AbstractFoo(int x, int y) { initialize(x, y); }
// This constructor and the following method allow
// subclass's readObject method to initialize our state.
protected AbstractFoo() { }
protected final void initialize(int x, int y) {
if (!init.compareAndSet(State.NEW, State.INITIALIZING))
throw new IllegalStateException("Already initialized");
this.x = x;
this.y = y;
... // Do anything else the original constructor did
init.set(State.INITIALIZED);
}
// These methods provide access to internal state so it can
// be manually serialized by subclass's writeObject method.
protected final int getX() { checkInit(); return x; }
protected final int getY() { checkInit(); return y; }
// Must call from all public and protected instance methods
private void checkInit() {
if (init.get() != State.INITIALIZED)
throw new IllegalStateException("Uninitialized");
}
... // Remainder omitted
}
// Serializable subclass of nonserializable stateful class
public class Foo extends AbstractFoo implements Serializable {
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
// Manually deserialize and initialize superclass state
int x = s.readInt();
int y = s.readInt();
initialize(x, y);
}
private void writeObject(ObjectOutputStream s)
throws IOException {
s.defaultWriteObject();
// Manually serialize superclass state
s.writeInt(getX());
s.writeInt(getY());
}
// Constructor does not use the fancy mechanism
public Foo(int x, int y) { super(x, y); }
private static final long serialVersionUID = 1856835860954L;
}
Inner classes(Item 22) should not implement Serializable. A static member class can, however, implement Serializable.
Summary
Unless a class is to be thrown away after a short period of use, implementing Serializable is a serious commitment that should be made with care. Extra caution is warranted if a class is designed for inheritance. For such classes, an intermediate design point between implementing Serializable and prohibiting it in subclasses is to provide an accessible parameterless constructor. This design point permits, but does not require, subclasses to implement Serializable.
Effective Java 74 Implement Serializable judiciously的更多相关文章
- Effective Java 11 Override clone judiciously
Principles If you override the clone method in a nonfinal class, you should return an object obtaine ...
- Effective Java 41 Use overloading judiciously
The choice of which overloading to invoke is made at compile time. // Broken! - What does this progr ...
- Effective Java 42 Use varargs judiciously
Implementation theory The varargs facility works by first creating an array whose size is the number ...
- Effective Java Index
Hi guys, I am happy to tell you that I am moving to the open source world. And Java is the 1st langu ...
- 《Effective Java》读书笔记 - 11.序列化
Chapter 11 Serialization Item 74: Implement Serializable judiciously 让一个类的实例可以被序列化不仅仅是在类的声明中加上" ...
- Effective Java 目录
<Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating ...
- 【Effective Java】阅读
Java写了很多年,很惭愧,直到最近才读了这本经典之作<Effective Java>,按自己的理解总结下,有些可能还不够深刻 一.Creating and Destroying Obje ...
- EFFECTIVE JAVA 第十一章 系列化
EFFECTIVE JAVA 第十一章 系列化(将一个对象编码成一个字节流) 74.谨慎地实现Serializable接口 *实现Serializable接口付出的代价就是大大降低了“改变这个类 ...
- Effective Java通俗理解(下)
Effective Java通俗理解(上) 第31条:用实例域代替序数 枚举类型有一个ordinal方法,它范围该常量的序数从0开始,不建议使用这个方法,因为这不能很好地对枚举进行维护,正确应该是利用 ...
随机推荐
- Android 学习笔记之如何使用SQLite数据库来保存数据...
PS:最近一阵子都在为考试复习...坑爹的计算机网络,复习了3天,最后该不会的还是不会...明天还考英语...真蛋疼... 学习内容: 1.使用SQLite数据库来保存数据... SQLite: ...
- CMD魔法堂:获取进程路径和PID值的方法集
一.前言 在开发发布更更新工具——更新Weblogic应用模块时,了解到更新Weblogic应用需要先关闭Weblogic应用窗口然后是清缓存.更新应用文件,最后再重启Weblogic应用窗口. ...
- 想要愉快入住酒店?缺了它还真不行!(含PPT)
编者注:别想歪了!我们说的是“机器学习”~ 在携程技术中心推出的线上公开课程[携程技术微分享]上,来自携程酒店研发的BI经理潘鹏举,介绍了如何借助大数据和算法,通过机器学习去克服酒店服务行业挑战,给用 ...
- 自定义JSTL标签和函数库
一.自定义JSTL标签 1.编写标签处理类: (1)实现 SimpleTag 接口,通过 setJspContext()方法可以获取到 jspContext 对象,实际上也是 pageContext ...
- sprint3 总结
sprint3 本次的主要任务是找项目中的bug,并与客户不断地沟通以满足客户的要求.队友主要负责找项目中的bug或提出一些建议.我主要是负责与客户沟通和修复bug.总的来说进展还算顺利. 团队贡献分 ...
- 设计模式--建造者(Builder)模式
将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示 --<设计模 ...
- 第一个Object-C类
转自:http://www.cnblogs.com/heyonggang/p/3441051.html 来源:http://www.cnblogs.com/mjios/archive/2013/04/ ...
- DataTable 获取列名 DataTable批量更新至数据库
好久没写东西了,这几个月也没下功夫钻研技术,愧疚啊.说下最近刚学会的DataTable 的用法吧,新手适合看下. 1 DataTable 获取列名 在处理数据的时候大家都会用到模型,从datatabl ...
- Web Service学习小结(概念性回忆)-希望你们会喜欢
Web Service的出现带来了很多系统工程直接相互的调用.无疑让代码的隐藏得到了好的封装. Web Service 它的主要的组成要素: SOAP:(Simple Object Access P ...
- .Net开源项目之开源论坛
.Net开源项目非常多,但是开源并且直接就能用的BBS项目就很少了,至少最近我在这上面没有找到一个合适的开源论坛.可能是因为我要求比较特殊,不但要开箱即用,还要用MVC+MySql开发. Discuz ...