不要在可序列化对象中缓存Singleton
如果你有一个对象其中某个字段保存了一个对Singleton的引用,那么这个对象在序列化读取后会导致在同一个虚拟机里Singleton对象有两个。比如下面的例子
public class Test3 {
public static void main(String[] args) throws IOException, ClassNotFoundException {
System.out.println(ABC.getInstance());
ByteArrayOutputStream out = new ByteArrayOutputStream();
new ObjectOutputStream(out).writeObject(ABC.getInstance());
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(out.toByteArray()));
ABC abc = (ABC) in.readObject();
System.out.println(abc);
}
}
class ABC implements Serializable {
private ABC() {}
private static ABC instance = new ABC();
public static ABC getInstance() {
return instance;
}
}
你会发现,打印出的两个ABC的instance是不一样的。解决方法很简单,在ABC加入这个方法
protected Object readResolve() {
return instance;
}
这样可以重置instance到这个虚拟机中的Singleton实例,还可以把引用instance的字段作为transient字段节省IO时间。
但是这不是最好的办法,最好就是,如果你知道ABC是Singleton,那么就永远不要把ABC赋值到你的对象成员变量里,getInstance()因为是static方法,编译器通常会做inline的,频繁调用不会导致频繁方法栈操作,所以缓存它意义不大。
没有评论:
发表评论