反序列化时如何正确使用过渡关键字?

问题描述 投票:0回答:1

我有以下课程

public class Num implements Serializable, Observable {
    private int num; // number which should be serialized

    // listeners who are watching for changes in this Num
    // No need to serialize these -- pointless to do so.
    private transient Set<Observer> listeners = new HashSet<>();

    @Override public void addListener(Observer o) { listeners.add(o); }

    @Override public void removeListener(Observer o) { listeners.remove(o); }

    public void set(int newVal) {
        if (num != newVal) {
            num = newVal; // set the value.
            for (Observer o : listeners)
                o.notify(); // Notify listeners that the value changed.
        }
    }
}

当我序列化此类时,它运行良好,并且保存了num。当我反序列化类时,会加载num,但是listeners 不会,并且设置为 null。然后我的程序在for (Observer o : listeners)行崩溃。

我想出了一些解决方案,但它们都是可怕的解决方案。

[1)有一种“重构” transient字段的设置方法。

public void setup() {
    if (listeners != null) throw new Exception("Already setup!");
    listeners = new HashSet<>();
}

这种方式很烦人,因为反序列化方法需要记住设置对象。对于从事此项目的其他人来说,这是非常不直观的。

[2)使set方法自动检查并自行修复

public void set(int newVal) {
    if (num != newVal) {
        if (listeners == null) listeners = new HashSet<>();
        ...
    }
}

这种方式也是不好的,因为即使检查只需要执行一次,检查也会不断发生。

[3)Observable中删除class Num,除去listeners等。然后创建一个包含Num实例的不可序列化的类。

public class Num implements Serializable {
    public int num;
}

public class ObservableNum impements Observable {
    private Num n;

    public ObservableNum() { n = new Num(); } // constructor
    private ObservableNum(Num n) { this.n = n; } // constructor

    ...

    public static ObservableNum loadNum(...) {

        ObjectInputStream ois = ...;
        return new ObservableNum((Num) ois.readObject());
    }
}

但是这种方式似乎也不必要地复杂。当然必须有更好的解决方案?如何正确使用瞬态?

java design-patterns serializable transient
1个回答
0
投票

方法2是很好的方法。在我的实践中,在将for循环或流/ foreach与集合一起使用时,我将始终检查null。

可以通过在addListener方法中初始化set来完成优化,因此,如果集合为空,则可以直接在set方法中返回。

关于您的性能,空检查语句不会影响性能,因为for循环和notify方法将花费更多时间,并且可以忽略。

© www.soinside.com 2019 - 2024. All rights reserved.