Java 使用反射将字符串转换为枚举值,其中枚举类型可以是多个类型中的任意一个
假设我有一个将另一个对象作为id的类:Java 使用反射将字符串转换为枚举值,其中枚举类型可以是多个类型中的任意一个,java,reflection,enums,Java,Reflection,Enums,假设我有一个将另一个对象作为id的类: public SomeClass { private final ID id; ... } ID的定义如下。请注意,将枚举拆分(分成逻辑组)的原因是,否则单个枚举将包含1000+个值。然后,该接口仍然需要使所有枚举都属于同一类型 public interface ID { public enum Name1 implements ID { ... constants ... } public enum Name2 imp
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\u VALUE”
映射到ID.Name2.SOME\u 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
我怎么会做这样的事?我在这里的反思中迷失了方向,在搜索了许多其他问题和答案之后,我似乎仍然没有接近答案
请注意,我还可以使用1000+整数常量实现这一点,并为此提供一个string>integer映射,但使用Enum感觉更干净。现在我遇到了这个障碍,我不再相信清洁了。我开始觉得我想把一个圆钉子装进一个方孔里
更新:我最终使用了被接受的答案作为解决方案,并对其进行了一点修改以使用我的代码:
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 getIdFromString(字符串键)
{
可选id=Arrays.stream(id.class.getDeclaredClasses())
.filter(类::isEnum)
.flatMap(aClass->Arrays.stream(aClass.getEnumConstants()))
.filter(enumValue->enumValue.toString().equals(键))
.findFirst();
return(ID)ID.get();
}
请注意,此代码根本不进行任何检查,因此您可能应该向其添加一些检查以处理无效键,甚至可能处理在
ID
中声明的枚举,但不实现ID
接口。您可以通过反射获得所有声明的类(包括枚举),并执行类似操作:
Arrays.stream(getClass().getDeclaredClasses())
.filter(Class::isEnum)
.flatMap(aClass -> Arrays.stream(aClass.getEnumConstants()))
.filter(enumValue -> enumValue.toString().equals(YOUR_VALUE_FROM_JSON))
.findFirst();
您可以通过反射(包括枚举)获取所有声明的类,并执行如下操作:
Arrays.stream(getClass().getDeclaredClasses())
.filter(Class::isEnum)
.flatMap(aClass -> Arrays.stream(aClass.getEnumConstants()))
.filter(enumValue -> enumValue.toString().equals(YOUR_VALUE_FROM_JSON))
.findFirst();
为什么要创建多个枚举,而不仅仅是一个,特别是考虑到它们嵌套在接口中?因为当我在Java中寻找大型枚举的最佳实践时,我发现了以下问题和答案:。枚举是编译时常量,这意味着当代码必须按名称引用它们时,它们最有用。如果您有这么多的枚举,您正在考虑将它们拆分,那么您真的在代码中按名称引用了所有这些枚举吗?或者您真的只是通过数据库中的字符串值来引用它们吗?如果是后者,那么它们首先就不应该是枚举。是的,每个枚举中的每个值都将在代码中的某个位置被引用至少一次(有些值将被多次引用)。正如我所说的,我也可以使用一个包含所有必需的string/int常量的类和一个映射函数,将标识符从json文件映射到内部string/int常量,但是枚举的设计不是为了避免使用这些“正常”常量吗?请注意,我没有直接使用外部字符串标识符作为这些对象的键,因为我只希望在代码内部使用有效的标识符。您的问题似乎是一种字符串插入问题。因此,通过定义
String
-常量,您的方法String getIdFromString(String str)
将只委托给str.intern()。巨型映射是jvm字符串表,查找可能比自定义巨型映射(虽然是O(1),但可能是更高的常量)或反射(O(n),其中n是常量数)更有效。为什么要创建多个枚举,而不是只创建一个,特别是考虑到它们嵌套在接口中?因为当我在Java中寻找大型枚举的最佳实践时,我发现了以下问题和答案:。枚举是编译时常量,这意味着当代码必须按名称引用它们时,它们最有用。如果您有这么多的枚举,您正在考虑将它们拆分,那么您真的在代码中按名称引用了所有这些枚举吗?或者您真的只是通过数据库中的字符串值来引用它们吗?如果是后者,那么它们首先就不应该是枚举。是的,每个枚举中的每个值都将在代码中的某个位置被引用至少一次(有些值将被多次引用)。正如我所说的,我也可以使用一个包含所有必需的string/int常量的类和一个映射函数,将标识符从json文件映射到内部string/int常量,但是枚举的设计不是为了避免使用这些“正常”常量吗?请注意,我没有直接使用外部字符串标识符作为这些对象的键,因为我只希望在代码内部使用有效的标识符。您的问题似乎是一种字符串插入问题。因此,通过定义String
-常量,您的方法String getIdFromString(String str)
将只委托给str.intern()。巨型映射是jvm字符串表,查找可能比自定义巨型映射(虽然是O(1),但可能是更高的常量)或反射(O(n),其中n是常量的数量)更有效确实知道哪些枚举是在ID
接口中定义的,并且可以在getIdFromString
中编写循环来搜索每个枚举,但我不希望每次添加或删除枚举时都向getIdFromString
方法添加(或删除)循环。使用反射将使这项工作与任意数量的已声明枚举一起进行。我已经更新了我的答案。告诉我它是否有助于感谢您的回答,但它似乎没有返回任何内容,即它返回的可选值为空(即使我传入的字符串与