Предположим, у меня есть класс, который принимает другой объект в качестве идентификатора:
public SomeClass
{
private final ID id;
...
}
ID
определяется следующим образом. Обратите внимание, что причина того, что перечисление разделено (на логические группировки), состоит в том, что одно перечисление в противном случае содержало бы более 1000 значений. В этом случае необходимо, чтобы все перечисления относились к одному и тому же типу.
public interface ID
{
public enum Name1 implements ID { ... constants ... }
public enum Name2 implements ID { ... constants ... }
public enum Name3 implements ID { ... constants ... }
...
}
И объект SomeClass
создается следующим образом:
SomeClass object = new SomeClass(ID.Name2.SOME_VALUE, ... more parameters};
Однако параметры, необходимые для создания объекта SomeClass
, хранятся в файле json, например:
{
"id": "SOME_VALUE",
...
}
Я хочу сопоставить строку "SOME_VALUE"
с ID.Name2.SOME_VALUE
. Теперь я мог бы сделать это, имея гигантскую карту:
Map<String, ID> conversionMap = HashMap<>();
conversionMap.put("SOME_VALUE", ID.Name2.SOME_VALUE);
conversionMap.put("SOME_OTHER_VALUE", ID.Name3.SOME_OTHER_VALUE);
... etc
, но я хочу сделать это автоматически, используя отражение от метода stati c внутри интерфейса ID
(некоторый очень грубый псевдокод):
public interface ID
{
public static ID getIdFromString(String key)
{
List<Enum> declaredEnums = ID.class.getDeclaredEnums();
for (Enum declaredEnum : declaredEnums)
{
for (EnumValue value : declaredEnum)
{
if (value.equals(key)
return value;
}
}
}
public enum Name1 implements ID { ... constants ... }
public enum Name2 implements ID { ... constants ... }
public enum Name3 implements ID { ... constants ... }
...
}
Как бы я поступил так? Я теряюсь в размышлениях здесь, и, просматривая множество других вопросов и ответов, я все еще, кажется, не ближе к ответу.
Обратите внимание, что я мог бы также реализовать это, используя более 1000 целочисленных констант и обеспечивая строка> целочисленное отображение для этого, но использование перечислений чувствует себя чище. Теперь, когда я наткнулся на эту загадку, я уже не так уверен в чистоте. Мне начинает казаться, что я пытаюсь вставить круглый колышек в квадратное отверстие.
ОБНОВЛЕНИЕ: я решил использовать принятый ответ в качестве решения и чуть-чуть изменил его для работы с моим кодом:
public static ID getIdFromString(String key)
{
Optional<?> id = Arrays.stream(ID.class.getDeclaredClasses())
.filter(Class::isEnum)
.flatMap(aClass -> Arrays.stream(aClass.getEnumConstants()))
.filter(enumValue -> enumValue.toString().equals(key))
.findFirst();
return (ID)id.get();
}
Помните, что этот код вообще не выполняет никакой проверки, поэтому вам, вероятно, следует добавить к нему некоторые проверки для обработки недействительных ключей и, возможно, даже для обработки перечислений, объявленных в ID
, но не реализуйте интерфейс ID
.