Подтвердить что ты не робот

Force Инициализация перечислимого типа в Java

Я пытаюсь найти способ заставить Java загружать/инициализировать перечисляемый тип (который вложен в класс, содержащий статическую карту).

Это важно для меня, потому что перечисляемый тип имеет конструктор, который заполняет указанную карту, и без явного способа инициализации этого перечисления карта останется пустой. Я попытался использовать Class.forName, но это не работает.

Я предполагаю, что могу создать экземпляр enum (и сохранить его в другой коллекции или что-то еще), но я хотел бы знать, есть ли элегантный способ сделать это.

4b9b3361

Ответ 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() );
  }
}