如何找出EnumMap中使用的枚举?

时间:2015-11-13 14:10:28

标签: java reflection enums

我有一个带有内部枚举和EnumMap的测试类,如下所示。如何找出EnumMap中使用的枚举?

enum MyEnum { ENUM1, ENUM2 }
EnumMap<MyEnum, String> emap = new EnumMap<>( MyEnum.class );
public void discover() {
  Class<?> eclass = ???;
  System.out.println( eclass );
}

应该打印

  

MyEnum.class

2 个答案:

答案 0 :(得分:6)

如果地图不为空,您可以检索一个键并检查其类。否则,唯一的方法是通过反射访问EnumMap的keyType私有字段(该字段不通过公共API公开)。

在第一种情况下,你可以这样做:

Iterator<?> it = map.keySet().iterator();
while (it.hasNext()) {
  Object key = it.next();
  if (key != null) return key.getDeclaringClass();
}

在第二种情况下(显然也适用于非空枚举),您可以使用:

private static Class<?> enumMapType(EnumMap<?, ?> map) {
  try {
    Field keyType = EnumMap.class.getDeclaredField("keyType");
    keyType.setAccessible(true);
    return (Class<?>) keyType.get(map);
  } catch (IllegalAccessException | NoSuchFieldException e) {
    throw new AssertionError("Could not find EnumMap type", e);
  }
}

如果EnumMap的内部实施发生变化,这可能会中断,最好找到解决方案的方法。

答案 1 :(得分:1)

如果EnumMap不为空,您可以使用

map.keySet().iterator().next().getDeclaringClass();
如果枚举有一个具有常量特定实现的方法,则

getClass()不起作用。

如果EnumMap为空,则可以使用反射,如@ assylias的回答所示。

另一种方法是继承EnumMap并编写一个public getter。

public final class MyEnumMap<K extends Enum<K>, V> extends EnumMap<K, V> {

    private final Class<K> keyType;

    public MyEnumMap(Class<K> keyType) {
        super(keyType);
        this.keyType = keyType;
    }

    public Class<K> keyType() { return keyType; }
}