这似乎是一个疯狂的错误,但{JD} 7 SE上Enum.valueOf(type, name)
似乎不稳定。
表现形式是,在完全相同的名称字符串(我已经验证过)上,对valueOf()
的调用有时会抛出IllegalArgumentException
消息No enum constant ...
。
我的团队通过Eclipse调试器运行了这个,我们注意到在enum上的valueOf的以下JDK实现中,enumConstantDirectory()
,即枚举的values()
列表,有时似乎是缺少一些价值观。不是枚举本身定义的所有值的全部。
我可以通过在JVM启动时调用Enum.valueOf(enumclass.class, "XXX")
来获取所有可能的枚举值来解决这个问题。当我这样做时,似乎values()
总是包含完整的集合。
但是,如果我不进行此类初始化,有时Enum.valueOf()
会抛出IllegalArgumentException
。
上下文:我在使用XStream 1.4.4转换转换枚举的POJO对象时遇到了这个问题,但XStream似乎并不存在这个问题。
有没有人见过这种错误?如果你有,我很想听听。 这令我难以置信。这是Oracle JDK / JVM实现中的错误吗?
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
其他相关细节:
我们正在使用org.reflections
库在启动时扫描代码中的所有枚举。在扫描期间,我们采用枚举的类型,并在与枚举关联的Class对象上调用clazz.getEnumConstants()
。这可能是一个相关的细节。
在查看和java.lang.Class.getEnumConstants()
实现时,它似乎在类中共享相同的enumConstants
共享对象。我想知道这里的实现是否存在问题。
我们的枚举很简单,没有静态初始化等等。
public enum ScreeningRuleType
{
INSERT,
CONFIRMATION,
AMOUNT,
EXISTENCE,
BAN,
SELECTION,
CUSTOM;
private long id;
private String descr;
ScreeningRuleType()
{
id = this.ordinal();
descr= this.toString().replace("_", " ");
}
}
修改 在试验这个时,我发现了另一种表现形式。在使用System.out初始化之后,现在不是抛出IllegalArgumentException,而是Enum.valueOf返回的值似乎是随机的。
这显示了我在Eclipse调试器中看到的内容。它清楚地显示我在字符串“EXISTENCE”和“EXISTENCE”.intern()上调用valueOf(),并清楚地显示它正在返回AMOUNT()。
答案 0 :(得分:6)
我忘了我遇到类似的东西 - 但我怀疑它是java-7之前的版本,可能已经回到Java 4/5天了。
问题在于,enum
附带的伴随结构的构建仅在第一次访问其中一个enum
时触发。不幸的是,如果您调用其中一种依赖于这些结构的方法,valueOf
或EnumSet.allOf
,例如之前访问其中一个enum
,它通常会灾难性地失败
可悲的是,我重构了代码,所以这不会发生,所以我不再有样本了。我会尝试重现这个问题并回复你。
我在这里看到 - Why the Java enum constants initialization is not complete?演示问题的另一个问题。
答案 1 :(得分:4)
实际上我们发现了这个问题。这是一个面子+掌上的时刻。我们通过尝试包含枚举的类的深(非浅)副本,通过反射API破坏了枚举。这具有消除单例枚举本身的所有实例变量的效果。感谢您的所有帮助和建议。