EnumMap的奇怪行为与来自不同类加载器的键

时间:2010-08-11 13:53:20

标签: java enums classloader

我遇到了由不同类加载器加载的枚举类型的奇怪行为。在公共库中,我有枚举定义(类似于以下内容):

enum MyEnumType { VAL_1, VAL_2, VAL_3 };

我有第一个创建以下地图的应用程序并将其注册为系统中的某种全局(注册代码只是为了简单起见):

final Map<MyEnumType, String> map = new EnumMap<MyEnumType, String>(MyEnumType.class);
map.put(MyEnumType.VAL_1, "value 1");
map.put(MyEnumType.VAL_2, "value 2");
map.put(MyEnumType.VAL_3, "value 3");
GLOBAL_SYSTEM_MAP = Collections.unmodifiableMap(map);

第二个应用程序(使用不同的类加载器)执行以下操作:

String value = GLOBAL_SYSTEM_MAP.get(MyEnumType.VAL_1);

并收到空值。我使用调试器检查GLOBAL_SYSTEM_MAP是否正确,包含适当的值,但get()方法仍然没有返回任何正确的值。

我怀疑原因可能与两个应用程序用来加载MyEnumType类型的不同类加载器有关。但另一方面,枚举的equals()方法可能就是为这种情况做好准备,不是吗?那么,也许EnumMap.get()实现使用==而不是equals()? (但我很怀疑)我也尝试用HashMap替换EnumMap,但这也没有解决问题。

2 个答案:

答案 0 :(得分:2)

EnumMap会根据创建的枚举类检查您传入的键的实际类。如果它们不同,get将返回null。由于您使用不同的类加载器两次加载MyEnum类,因此该类将有所不同。

修复是安排两个应用程序使用MyEnum类的共享实例。

答案 1 :(得分:1)

不同类加载器加载的

enum值不应该是==equals。如果从不同的类加载器中处理具有相同名称的不同类,则通常会出现某种错误。类型为GLOBAL_SYSTEM_MAP Map<MyEnumType,String>Map<?,String>(或类似)?

隐藏错误的一个可能原因是某些类加载器不首先委托给它们的父级(IIRC,打破了EE规范推荐的Java SE规范)。这会导致各种各样的问题。