有些书可以极大地改变您的生活。 其中一本是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