有些书可以极大地改变您的生活。 其中一本是Joshua Bloch撰写的“ Effective Java” 。 在下面您可能会发现一些小的实验,该实验的灵感来自于本书的第11章“串行化”。
假设我们有一个为继承而设计的类,它本身不是可序列化的 ,并且没有无参数的构造函数,如以下示例所示:
public class CumbersomePoint {
private String name;
private double x;
private double y;
protected CumbersomePoint(double x, double y, String name) {
this.x = x;
this.y = y;
this.name = name;
}
public String getName() {
return name;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
...
}
现在,当我们扩展此类时,例如通过以下方式:
public class ConvenientPoint extends CumbersomePoint implements Serializable {
public ConvenientPoint(double x, double y, String name) {
super(x, y, name);
}
...
}
并尝试序列化然后反序列化任何ConvenientPoint实例,我们将很快遇到漂亮的InvalidClassException ,抱怨没有有效的构造函数。 在您应用称为序列化代理模式的技术之前,情况看起来有点绝望。
首先,将内部类添加到ConvenientPoint类中:
private static class SerializationProxy implements Serializable {
private String name;
private double x;
private double y;
public SerializationProxy(ConvenientPoint point) {
this.name = point.getName();
this.x = point.getX();
this.y = point.getY();
}
private Object readResolve() {
return new ConvenientPoint(x, y, name);
}
}
SerializationProxy类将表示封闭类实例的逻辑状态。 我们还必须向ConvenientPoint类添加以下方法:
private Object writeReplace() {
return new SerializationProxy(this);
}
现在,当ConvenientPoint实例将被序列化时,由于writeReplace方法,它将提名其替换对象– SerializationProxy实例将被序列化而不是ConvenientPoint 。
另一方面,当序列化代理将被反序列化时, readResolve方法的使用将提名其替代品,即ConvenientPoint实例。
如您所见,无论缺少不可序列化的父类的无参数构造函数,我们都使ConvenientPoint可序列化。
在本文的结尾,再说一遍–如果要防止破坏由构造函数强制执行的类不变式,可以使用序列化代理模式 (在我们的示例中为ConvenientPoint)在类中添加以下方法:
private void readObject(ObjectInputStream stream) throws InvalidObjectException {
throw new InvalidObjectException("Use Serialization Proxy instead.");
}
它将防止封闭类的反序列化。
翻译自: https://www.javacodegeeks.com/2014/06/serialization-proxy-pattern-example.html
这篇博客探讨了如何使用序列化代理模式解决在Java中处理非序列化父类时遇到的问题。通过示例展示了如何创建内部类SerializationProxy来保存逻辑状态,并利用writeReplace和readResolve方法确保在序列化和反序列化过程中的正确性。

3万+

被折叠的 条评论
为什么被折叠?



