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

标签 java serialization

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

在Effective java中,作者谈到了这个话题。

Naively adding a parameterless constructor and a separate initialization method to a class whose remaining constructors establish its invariants would complicate the state space, increasing the likelihood of error.

以下代码复制自Effective Java 第二版[第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

    }

All public and protected instance methods in AbstractFoo must invoke checkInit before doing anything else. This ensures that method invocations fail quickly and cleanly if a poorly written subclass fails to initialize an instance. Note that the initialized field is an atomic reference (java.util.concurrent. atomic.AtomicReference). This is necessary to ensure object integrity in the face of a determined adversary. In the absence of this precaution, if one thread were to invoke initialize on an instance while a second thread attempted to use it, the second thread might see the instance in an inconsistent state.

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

最佳答案

我在看这本书的时候也遇到了同样的问题。我在那个地方有点困惑。经过一些研究,我发现了这一点。

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

阅读本文。据那 “在反序列化期间,将使用该类的公共(public)或 protected 无参数构造函数来初始化不可序列化类的字段。无参数构造函数必须可供可序列化的子类访问。可序列化子类的字段将被恢复来自流”

我想这回答了你的问题。 希望这会有所帮助。 如果本评论有什么错误的地方,欢迎指正。

关于java - 将无参数构造函数添加到不可序列化的可扩展类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8080605/

相关文章:

java - 使用 jboss EAP 7 发送 JMS(消息)时出错

java - 将一些东西保存到 JAR 中

node.js - 如何使用passport.js正确实现serializeUser?

发布日期字段时djangorest 400响应

java - 如何使用 Java lambda 仅窗口化 Kafka Streams 中的输入?

java - 将文本区域添加到 FlowLayout 面板 Java Swing

java - Android Activity 显示内容的时间太长

python - 在 Python 中序列化二进制数据

java - getExtras().getSerialized(key) 和 getSerializedExtra(name) 之间有什么区别

java - 如何将第三方 jar 添加到本地 Maven 存储库?