Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用反射将字符串转换为枚举值,其中枚举类型可以是多个类型中的任意一个_Java_Reflection_Enums - Fatal编程技术网

Java 使用反射将字符串转换为枚举值,其中枚举类型可以是多个类型中的任意一个

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

假设我有一个将另一个对象作为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\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
方法添加(或删除)循环。使用反射将使这项工作与任意数量的已声明枚举一起进行。我已经更新了我的答案。告诉我它是否有助于感谢您的回答,但它似乎没有返回任何内容,即它返回的可选值为空(即使我传入的字符串与