【发布时间】:2023-04-04 23:09:01
【问题描述】:
假设我有一个将另一个对象作为 id 的类:
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
但我想使用来自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接口。
【问题讨论】:
-
为什么要创建多个枚举,而不是一个,尤其是考虑到它们嵌套在界面内?
-
因为当我在 Java 中寻找大型枚举的最佳实践时,我发现了这个问题和答案:stackoverflow.com/questions/8671088/…。
-
枚举是编译时常量,这意味着当代码必须按名称引用它们时,它们最有用。如果您有这么多枚举,您正在考虑将它们拆分,那么您真的是在代码中按名称指代所有枚举吗?或者你真的只是通过字符串值来引用它们,例如数据库?如果是后者,那么它们首先不应该是枚举。
-
是的,每个枚举中的每个值都将在代码中的某处至少被引用一次(有些将被多次引用)。正如我所说,我也可以使用一个包含所有必需的字符串/整数常量的类和一个映射函数,将标识符从 json 文件映射到内部字符串/整数常量,但枚举并不是为了避免使用这些而设计的“正常”常数?请注意,我没有直接使用外部字符串标识符作为这些对象的键,因为我只想在代码中使用有效的标识符。
-
您的问题似乎是一种字符串实习问题。因此,通过定义
String-constants 和您的方法String getIdFromString(String str)将只委托给str.intern(),您可能会更有效率。巨型地图是 jvm 字符串表,查找可能比自定义巨型地图(但 O(1) 但可能更高的常数)或反射(O(n),其中 n 是常数的数量)更有效。
标签: java reflection enums