当前位置: 首页 > 面试题库 >

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

姬天逸
2023-03-14
问题内容

这是此问题的后续措施。该解决方案防水吗?

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];
    }
}

问题答案:

该解决方案防水吗?

否。(尽管可能就足够了,取决于使用代码的方式和位置。)

条目77:例如实例控件中,更喜欢枚举类型来读取readResolve (Effective
Java,第二版
),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];
    }

  }

}

但是,就像从互联网上复制任何与安全相关的内容一样,需要警告。我绝不是专家。



 类似资料:
  • 问题内容: 在Java 1.5之前的世界中(尚无enum),并且我的对象已被序列化,如何执行适当的实例控制?我说的是这样的类,据我所知,我不确定instance0和instance1将始终是唯一的实例。 问题答案: 您应该真正查看有效Java。关于的一章对此进行了一定程度的论述,而关于模式的一章无疑对实现方式产生了影响enum。 简短的答案是您必须实施readResolve。

  • 问题内容: 考虑示例: 我们怎么能做到这一点(而价值 确实 发生了变化)? 枚举实例不是隐式 静态的 并且是 final的 吗?另外,既然是,为什么我可以在其他课程之外访问它? 问题答案: 似乎没有人解决私人方面的问题。我的猜测是您正在从包含类型访问私有字段-您的枚举 实际上 是嵌套类型,如下所示: 这是完全合法和正常的-您 始终 可以从包含的类型访问嵌套类型的私有成员。 如果将枚举设置为顶级类型

  • 问题内容: 这可能是一个非常幼稚的问题。 我曾经相信Java 中的a 总是 包含堆栈跟踪。这是正确的吗? 现在看起来我捕获了 没有 堆栈跟踪的异常。是否有意义?是否 可以 在没有堆栈跟踪的情况下捕获异常? 问题答案: 无需堆栈跟踪就可以捕获Java中的Throwable对象: 构造一个具有指定详细消息,原因,启用或禁用原因,启用或禁用 可写堆栈跟踪 的新throwable 。 填写执行堆栈跟踪。此

  • 现在看来,我在没有堆栈跟踪的情况下捕获异常。有道理吗?是否有可能在没有堆栈跟踪的情况下捕获异常?

  • 是否可以在不创建新实例的情况下更改java中File类的文件路径? 返回 现在我想转到父目录。我想我可以用这样的东西 但我得用 我还有其他方法可以达到同样的效果吗?或者我可以创建多个实例,将它们存储在一个数组中,同时处理两个对象(目录)?

  • 本文向大家介绍Java枚举类用法实例,包括了Java枚举类用法实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Java枚举类用法。分享给大家供大家参考。具体如下: 希望本文所述对大家的java程序设计有所帮助。