Force Инициализация перечислимого типа в Java
Я пытаюсь найти способ заставить Java загружать/инициализировать перечисляемый тип (который вложен в класс, содержащий статическую карту).
Это важно для меня, потому что перечисляемый тип имеет конструктор, который заполняет указанную карту, и без явного способа инициализации этого перечисления карта останется пустой. Я попытался использовать Class.forName
, но это не работает.
Я предполагаю, что могу создать экземпляр enum (и сохранить его в другой коллекции или что-то еще), но я хотел бы знать, есть ли элегантный способ сделать это.
Ответы
Ответ 1
Класс загружается при обращении к классу. Это работает одинаково для всех классов.
У вас больше вероятность того, что значение Enum инициализируется перед любым статическим блоком. то есть вы не можете ссылаться на что-то инициализированное в статическом блоке в конструкторе. (Обычно инициализация статического содержимого в конструкторе является идеей BAD). Вам нужно инициализировать карту в статическом блоке, а не в конструкторе.
Try
import java.util.Map;
import java.util.HashMap;
public enum EnumTest {
FOO, BAR, BAZ;
private static final Map<String,EnumTest> map = new LinkedHashMap<String,EnumTest>();
static {
for(EnumTest e : EnumTest.values())
map.put(e.name(), e);
}
public static void main(String... args) {
System.out.println(EnumTest.map);
}
}
Ответ 2
Не можете ли вы просто инициализировать карту в статическом инициализаторе типа Enum?
public enum SomeEnum
{
Member1, Member2, Member3 ...
private static Map<K, SomeEnum> map = ...;
static
{
...populate map...
}
...
EDIT: Похоже, что проблема заключалась в том, что определения членов Enum должны быть первыми. Наверное, я просто замалчивал это. Я установил пример.
Ответ 3
Вы можете просто ссылаться на что-то в классе enum. Например:
public class EnumTest {
static final Map<String, MyEnum> map = new HashMap<String, MyEnum>();
enum MyEnum {
FOO, BAR, BAZ;
MyEnum() {
map.put(name(), this);
}
}
static {
// ensure MyEnum is initialized
MyEnum.values();
}
public static void main(String[] argsa) {
System.out.println(map.size());
}
}
Ответ 4
Похоже, это именно то, почему часто рекомендуется использовать методы доступа, а не напрямую ссылаться на членов. Ваша проблема в том, что код позволяет получить доступ к карте до ее инициализации. Блокируйте произвольный доступ к карте и спрятайте ее за методом доступа, чтобы убедиться, что она инициализирована.
import java.util.Map;
import java.util.HashMap;
public enum EnumTest {
FOO, BAR, BAZ;
private static Map<String,EnumTest> map = null;
public synchronized static Map getMap() {
if (map == null) {
map = new HashMap<String,EnumTest>();
for ( EnumTest e : EnumTest.values() ) {
map.put( e.name(), e );
}
}
return map;
}
public static void main(String[] args) {
System.out.println( EnumTest.getMap().size() );
}
}