I stumbled across a strange difference in behaviour between enums in Java without any defined methods and those that do: In the latter case, Enum.class
and Enum.getClass()
actually refer to different compiled classes, i.e. !Enum.class.equals(Enum.getClass())
; This causes problems when trying to e.g. instantiate an EnumMap
with a class specified only at runtime:
import java.util.EnumMap;
public class EnumMapTest {
private enum TestEnum {
FOO;
}
private enum TestEnumWithMethod {
BAR {
@Override
protected void doSomething() {
}
};
protected abstract void doSomething();
}
public static void main(String[] args) {
System.out.println(String.format("Testing enum %s...", TestEnum.class));
final Class<TestEnum> enumStaticClass = TestEnum.class;
System.out.println(String.format("EnumMap construction using static %s...", enumStaticClass));
new EnumMap<TestEnum, Object>(enumStaticClass);
final Class<TestEnum> enumDynamicClass = (Class<TestEnum>) TestEnum.FOO.getClass();
System.out.println("Are the static and dynamic classes equal? " + enumStaticClass.equals(enumDynamicClass));
System.out.println(String.format("EnumMap construction using dynamic %s...", enumDynamicClass));
new EnumMap<TestEnum, Object>(enumDynamicClass);
System.out.println(String.format("Testing enum %s...", TestEnumWithMethod.class));
final Class<TestEnumWithMethod> enumWithMethodStaticClass = TestEnumWithMethod.class;
System.out.println(String.format("EnumMap construction using static %s...", enumWithMethodStaticClass));
new EnumMap<TestEnumWithMethod, Object>(enumWithMethodStaticClass);
final Class<TestEnumWithMethod> enumWithMethodDynamicClass = (Class<TestEnumWithMethod>) TestEnumWithMethod.BAR.getClass();
System.out.println("Are the static and dynamic classes equal? " + enumWithMethodStaticClass.equals(enumWithMethodDynamicClass));
System.out.println(String.format("EnumMap construction using dynamic %s...", enumWithMethodDynamicClass));
new EnumMap<TestEnumWithMethod, Object>(enumWithMethodDynamicClass);
}
}
The corresponding console output is:
Testing enum class EnumMapTest$TestEnum...
EnumMap construction using static class EnumMapTest$TestEnum...
Are the static and dynamic classes equal? true
EnumMap construction using dynamic class EnumMapTest$TestEnum...
Testing enum class EnumMapTest$TestEnumWithMethod...
EnumMap construction using static class EnumMapTest$TestEnumWithMethod...
Are the static and dynamic classes equal? false
EnumMap construction using dynamic class EnumMapTest$TestEnumWithMethod$1...
Exception in thread "main" java.lang.NullPointerException
at java.util.EnumMap.initialization(EnumMap.java:726)
at java.util.EnumMap.<init>(EnumMap.java:395)
at EnumMapTest.main(EnumMapTest.java:46)
Why are there two classes made for the enum with methods? Why does this cause problems during the instantiation of EnumMap
? How can I get around this to create an instance without knowing the exact enum type at compile time?
I found the problem:
Enum.getClass()
gets the anonymous class of the particular enum instance, e.g.FOO
orBAR
, whileEnum.getDeclaringClass()
gets the class of the actual enum. Strange that the latter stills works without methods, though...