将无参数构造函数添加到不可序列化的可扩展类

时间:2011-11-10 13:56:53

标签: java serialization

将addid无参数构造函数添加到不可序列化的可扩展类中有什么特别之处。

在Effective java中,作者讨论了这个主题。

  

天真地添加一个无参数构造函数和一个   将初始化方法分离到剩余构造函数建立其类的类   不变量会使状态空间复杂化,增加出错的可能性。

从Effective Java 2nd Edition [页292-293]

复制以下代码
 public 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

    }
  

AbstractFoo中的所有公共和受保护实例方法都必须调用   在执行任何其他操作之前checkInit。这可确保方法调用失败   如果写得不好的子类无法初始化实例,请快速而干净地进行。注意   初始化字段是原子引用(java.util.concurrent。   atomic.AtomicReference)。这对于确保对象的完整性是必要的   面对坚定的对手。在没有这种预防措施的情况下,如果有一个线程   在第二个线程试图使用时调用实例上的初始化   它,第二个线程可能会看到实例处于不一致状态。

我们为什么要这样做?我没有完全理解这一点。谁能解释一下?

2 个答案:

答案 0 :(得分:3)

我在阅读这本书时遇到了同样的问题。我在那个确切的地方有点困惑。通过一些研究,我发现了这一点。

http://docs.oracle.com/javase/7/docs/api/java/io/Serializable.html

阅读本文。根据那个 “在反序列化期间,非序列化类的字段将使用类的public或protected no-arg构造函数进行初始化。对于可序列化的子类,必须可以访问no-arg构造函数。可序列化子类的字段将被恢复来自流“

我认为这可以回答你的问题。 希望这会有所帮助。 如果此评论中有任何错误,请随时更正。

答案 1 :(得分:0)

当您遇到多线程问题时,单独的初始化方法非常有用。你可以看到好文章:http://www.ibm.com/developerworks/java/library/j-jtp0618/index.html