跟进:Java中没有枚举的实例控件

这是 this question的后续行动.这个解决方案是否具有防水功能
public final class Thing implements Serializable {

    private static final long serialVersionUID = 1L;

    private static final Thing[] instances = new Thing[2];
    private static int nextOrdinal = 0;

    public static final Thing instance0 = new Thing("whatever0");
    public static final Thing instance1 = new Thing("whatever1");

    private transient final String someState;

    public String someMethod() {return someState;}

    private final int ordinal;

    private Thing(String someState) {
        this.someState = someState;
        this.ordinal = nextOrdinaL++;
        instances[this.ordinal] = this;
    }

    private Object readResolve() throws ObjectStreamException {
        return instances[this.ordinal];
    }
}

解决方法

Is this solution watertight?

不.(虽然它可能是足够的,取决于代码的使用方式和位置.)

在第77项中:对于实例控制,首选枚举类型为readResolve(Effective Java,2nd ed),Bloch演示了攻击者如何拥有像您这样的类返回任何值.攻击依赖于手工制作的字节输入,并且能够在目标上运行代码(因此,如果在沙盒环境中使用,某些RMI情况等,则代码可能存在安全风险).我不知道这是否是唯一的攻击 – 它是唯一提到的攻击.解决方案是声明所有字段是瞬态的,但是您遇到了如何存储值的问题.

您可以使用序列化代理模式解决这些问题(书中的第78项 – 每个阅读它的Java程序员都推荐它的原因).

public final class Thing implements Serializable {
  private static final long serialVersionUID = 1L;
  private static final Thing[] INSTANCES = new Thing[2];
  private static int NEXT_ORDINAL = 0;

  public static final Thing INSTANCE0 = new Thing(
      "whatever0");
  public static final Thing INSTANCE1 = new Thing(
      "whatever1");

  private transient final String someState;

  public String someMethod() {
    return someState;
  }

  private final int ordinal;

  private Thing(String someState) {
    this.someState = someState;
    ordinal = NEXT_ORDINAL++;
    INSTANCES[ordinal] = this;
  }

  private Object writeReplace() {
    return new ThingProxy(this);
  }

  private void readobject(ObjectInputStream stream)
      throws InvalidobjectException {
    throw new InvalidobjectException("Proxy required");
  }

  private static class ThingProxy implements Serializable {
    private static final long serialVersionUID = 1L;
    private final int ordinal;

    private ThingProxy(Thing t) {
      ordinal = t.ordinal;
    }

    private Object readResolve()
        throws ObjectStreamException {
      return INSTANCES[ordinal];
    }

  }

}

虽然,与复制任何与互联网相关的安全性一样,但需要注意.我绝不是专家.

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...