这是此问题的后续措施。该解决方案防水吗?
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程序设计有所帮助。