Я наткнулся на странную разницу в поведении между перечислениями на Java без каких-либо определенных методов и тех, которые делают: В последнем случае Enum.class
и Enum.getClass()
действительно относятся к разным скомпилированным классам, т.е. !Enum.class.equals(Enum.getClass())
; Это вызывает проблемы при попытке, например, экземпляр EnumMap
с классом указывается только во время выполнения:Не удается создать экземпляр EnumMap с аргументом динамического класса для перечислений с помощью методов
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);
}
}
Соответствующий выход консоли:
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)
Почему существует два класса, сделанные для перечисления с методами? Почему это вызывает проблемы при создании EnumMap
? Как я могу обойти это, чтобы создать экземпляр без знания точного типа перечисления во время компиляции?
Это не мой вопрос: в моем случае у меня нет информации о классе во время компиляции. См. Мой ответ ниже – errantlinguist
@errantlinguist Просьба уточнить ваш предполагаемый прецедент. Любой общий метод, который будет создавать «EnumMap» или иным образом должен знать класс «enum», должен иметь класс как вход (например, для «EnumSet # noneOf'); если вы перейдете в «BAR», вам все равно придется указывать «TestEnumWithMethod» как параметр типа для того, что вы его передаете. – chrylis
Извините, вы ответили «почему» на мой вопрос, но если я опубликую текущую проблему с реализацией, я скажу, что опубликую «минимальный рабочий пример». В моем случае у меня есть контейнер экземпляров «Enum», который не является «EnumSet» - моим точным случаем, «List», потому что мне нужно заказать перечисления. Я обобщил метод работы с несколькими типами перечислений, и он работал во всех случаях, кроме тех случаев, когда перечисления имеют определенные методы. – errantlinguist