The readResolve feature allows you to substitute another instance for the one created by readObject [Serialization, 3.7].

If the class of an object being deserialized defines a readResolve method with the proper declaration, this method is invoked on the newly created object after it is deserialized. The object reference returned by this method is then returned in place of the newly created object. In most uses of this feature, no reference to the newly created object is retained, so it immediately becomes eligible for garbage collection.

public class Elvis implements Serializable {

/**

* The version UID for the serial version object.

*/

private static final long serialVersionUID = 4285474589312744336L;

public static final Elvis INSTANCE = new Elvis();

private Elvis() {

}

// readResolve for instance control - you can do better!

private Object readResolve() {

// Return the one true Elvis and let the garbage collector take care of the Elvis impersonator.

return INSTANCE;

}

public static void main(String[] args) {

ByteArrayOutputStream os = new ByteArrayOutputStream();

ObjectOutputStream oos;

try {

oos = new ObjectOutputStream(os);

oos.writeObject(Elvis.INSTANCE);

oos.close();

ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());

ObjectInputStream ois = new ObjectInputStream(is);

Elvis e = (Elvis) ois.readObject();

System.out.printf("Elvis is %s the one used before? ",

e == Elvis.INSTANCE? "": "not");

ois.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (ClassNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

Note

If you depend on readResolve for instance control, all instance fields with object reference types must be declared transient. If a singleton contains a nontransient object reference field, the contents of this field will be deserialized before the singleton's readResolve method is run.

A demo for attack to secure a reference to the deserialized object before its readResolve method is run.

First, write a "stealer" class that has both a readResolve method and an instance field that refers to the serialized singleton in which the stealer "hides." In the serialization stream, replace the singleton's nontransient field with an instance of the stealer. You now have a circularity: the singleton contains the stealer and the stealer refers to the singleton.

Because the singleton contains the stealer, the stealer's readResolve method runs first when the singleton is deserialized. As a result, when the stealer's readResolve method runs, its instance field still refers to the partially deserialized (and as yet unresolved) singleton.

The stealer's readResolve method copies the reference from its instance field into a static field, so that the reference can be accessed after the readResolve method runs. The method then returns a value of the correct type for the field in which it's hiding. If it didn't do this, the VM would throw a ClassCastException when the serialization system tried to store the stealer reference into this field.

// Broken singleton - has nontransient object reference field!

public class Elvis implements Serializable {

private static final long serialVersionUID = 1L;

public static final Elvis INSTANCE = new Elvis();

private Elvis() {

}

private String[] favoriteSongs = { "Hound Dog", "Heartbreak Hotel" }; // favorite field

public void printFavorites() {

System.out.println(Arrays.toString(favoriteSongs));

}

private Object readResolve() throws ObjectStreamException {

return INSTANCE;

}

}

public class ElvisStealer implements Serializable {

static Elvis impersonator;

private Elvis payload;

private Object readResolve() {

// Save a reference to the "unresolved" Elvis instance

impersonator = payload;

// Return an object of correct type for favorites field

return new String[] { "A Fool Such as I" };

}

private static final long serialVersionUID = 0;

}

You could fix the problem by declaring the favorites field transient, but you're better off fixing it by making Elvis a single-element enum type (Item 3).

// Enum singleton - the preferred approach

public enum Elvis {

INSTANCE;

private String[] favoriteSongs = { "Hound Dog", "Heartbreak Hotel" };

public void printFavorites() {

System.out.println(Arrays.toString(favoriteSongs));

}

}

The accessibility of readResolve is significant.

If you place a readResolve method on a final class, it should be private.

If you place a readResolve method on a nonfinal class, you must carefully consider its accessibility.

If it is private, it will not apply to any subclasses.

If it is package-private, it will apply only to subclasses in the same package.

If it is protected or public, it will apply to all subclasses that do not override it.

If a readResolve method is protected or public and a subclass does not overriden it, deserializing a serialized subclass instance will produce a superclass instance, which is likely to cause a ClassCastException.

Summary

You should use enum types to enforce instance control invariants wherever possible. If this is not possible and you need a class to be both serializable and instance-controlled, you must provide a readResolve method and ensure that all of the class's instance fields are either primitive or transient.

Effective Java 77 For instance control, prefer enum types to readResolve的更多相关文章

  1. Effective Java 31 Use instance fields instead of ordinals

    Principle Never derive a value associated with an enum from its ordinal; store it in an instance fie ...

  2. Effective Java 19 Use interfaces only to define types

    Reason The constant interface pattern is a poor use of interfaces. That a class uses some constants ...

  3. Effective Java 37 Use marker interfaces to define types

    Marker interface is an interface that contains no method declarations, but merely designates (or &qu ...

  4. 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 ...

  5. 《Effective Java》读书笔记 - 11.序列化

    Chapter 11 Serialization Item 74: Implement Serializable judiciously 让一个类的实例可以被序列化不仅仅是在类的声明中加上" ...

  6. Effective Java 目录

    <Effective Java>目录摘抄. 我知道这看起来很糟糕.当下,自己缺少实际操作,只能暂时摘抄下目录.随着,实践的增多,慢慢填充更多的示例. Chapter 2 Creating ...

  7. 【Effective Java】阅读

    Java写了很多年,很惭愧,直到最近才读了这本经典之作<Effective Java>,按自己的理解总结下,有些可能还不够深刻 一.Creating and Destroying Obje ...

  8. Effective Java 第二版 Enum

    /** * Effective Java 第二版 * 第30条:用enum代替int常量 */ import java.util.HashMap;import java.util.Map; publi ...

  9. Effective Java Chapter4 Classes and Interface

    MInimize the accessibility of classes and members 这个叫做所谓的 information hiding ,这么做在于让程序耦合度更低,增加程序的健壮性 ...

随机推荐

  1. HTML简明教程(一)

    HTML简明教程(一) 内容主体来自:W3School 一.HTML 简介 二.HTML 基础 三.HTML 元素 四.HTML 属性 五.HTML 标题 六.HTML 段落 七.HTML 文本格式化 ...

  2. linux内核分析课程笔记(二)

    运行一个精简的操作系统内核 存储程序计算机是几乎所有计算机的基础逻辑框架. 堆栈是计算机中非常基础的东西,在最早计算机没有高级语言时,在高级语言出现之前,我们没有函数的概念.但高级语言出现后有了函数调 ...

  3. Spring总结——AOP、JDBC和事务的总结

    1.上一次总结了 Spring 的核心三大组件(Core,Beans,Context),今天总结的 AOP.JDBC和事务都可以看成是核心三大组件的应用. 其中 Spring 的事务管理又以 AOP ...

  4. Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划)

    Scrum 3.1 多鱼点餐系统开发进度(第三阶段项目构思与任务规划) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题:餐厅到 ...

  5. 数论 - n元线性同余方程的解法

    note:n元线性同余方程因其编程的特殊性,一般在acm中用的很少,这里只是出于兴趣学了一下 n元线性同余方程的概念: 形如:(a1*x1+a2*x2+....+an*xn)%m=b%m       ...

  6. 利用mciSendString播放音频

    最近在写音频播放器,不过有点懒散,开发进度很慢,一天只做了一点点东西.其实就是让程序能播放音频.这个在我大二学winform程序开发时书上有说,那是书上教的是用media player的COM组件,而 ...

  7. C#-Windows服務以LocalSystem賬戶安裝的話無法獲取我的文檔路徑

    如圖,如果Window服務以上圖 Account安裝運行,則無法獲取到 以下路徑: System.Environment.GetFolderPath(Environment.SpecialFolder ...

  8. 分享一些WinForm数据库连接界面UI

    1.动软代码生成器源码中. 2.DevExpress控件包中有类似的界面 3.代码生成器:http://www.csharpwin.com/csharpspace/11666r2577.shtml 4 ...

  9. 在MVC中应用百度富文本编辑器

    1.下载.NET版本的百度富文本编辑器,前往 下载.NET版本百度富文本框 2.解压下载的.zip压缩包,将utf8-.net文件夹名称改为:ueditor,复制到MVC根目录下面.结构如下: App ...

  10. [PE结构分析] 5.IMAGE_OPTIONAL_HEADER

    结构体源代码如下: typedef struct _IMAGE_OPTIONAL_HEADER { // // Standard fields. // +18h WORD Magic; // 标志字, ...