问题描述
所以我有一个带有多个枚举的 java 类
public class Enumerations {
public enum Days {
Monday("MON")
Tuesday("Tue")
string value;
private Days(String value){
this.value = value
}
public string getValue(){
return this.value;
}
}
public enum Months{
January("JAN")
APRIL("APR")
string value;
private Months(String value){
this.value = value
}
public string getValue(){
return this.value;
}
}
}
现在我有另一个类,我想通过字符串访问枚举类,因为我无法直接实例化枚举,因为我不知道要使用的枚举并从变量字符串访问枚举值(不知道这是因为好)。
class EnumParser{
public static void main(String args[]){
String enum = "Days"; //Will get this value from external source so its variable(Can be months or days)
String value = "Monday" //This is going to variable as well with value unknown.
}
}
那么我如何在这里使用字符串变量将输出作为“MON”
Enumerations.{{Days}}.{{Monday}}.getValue();
编辑了问题以获得更清晰的观点,这两天和周一都是变量。
1楼
您可以使用if-else
或switch
语句来确定要使用的枚举,然后使用valueOf()
:
String e = "Days";
String value = "Monday";
if (e.equalsIgnoreCase(Enumerations.Days.class.getSimpleName())) {
System.out.println(Enumerations.Days.valueOf(value).getValue());
} else if (e.equalsIgnoreCase(Enumerations.Months.class.getSimpleName())) {
System.out.println(Enumerations.Months.valueOf(value).getValue());
} else {
System.out.println("Could not find enum");
}
输出:
MON
根据您可能有 200 多个枚举的评论进行更新:
您可以像这样使用反射:
String e = "Days";
String value = "Monday";
String res = Arrays.stream(Enumerations.class.getDeclaredClasses())
.filter(c -> c.getSimpleName().equalsIgnoreCase(e))
.findFirst()
.map(c -> {
String result = null;
try {
Object o = c.getMethod("valueOf", String.class).invoke(null, value);
result = (String) o.getClass().getMethod("getValue").invoke(o);
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e1) {
e1.printStackTrace();
}
return result;
}).orElse("Could not find");
System.out.println(res); //prints MON
2楼
制作一个静态方法,为您检索适当的枚举值:
//inside Days, skips some excess array creation
private static final Days[] VALUES = Days.values();
public static Days getDay(String day) {
return Arrays.stream(VALUES)
.filter(d -> d.value.equalsIgnoreCase(day))
.findAny(); //Optional<Days>
//can use #orElse/#orElseThrow to decide behavior for a mismatch
}
然后就是直接获取枚举的问题:
Days monday = Days.getDay("MON");
如果您愿意,您可以创建多种方法来过滤这些输入。
更进一步,如果您真的想发疯,您可以传递Predicate<Days>
(或任何枚举)并以这种方式过滤:
public static Days getDay(Predicate<Days> filter) {
return Arrays.stream(VALUES)
.filter(filter)
//In this case I'm returning null for no match
.findAny().orElse(null);
}
然后:
Days monday = Days.getDay(d -> d.getValue().equalsIgnoreCase("MON"));
现在在Monday
的严格情况下,您可以使用Days#valueOf
,但是如果您搜索的字符串没有枚举常量,这将引发错误。
Days monday = Days.valueOf("Monday"); //okay
//all of these below would throw an error
monday = Days.valueOf("monday");
monday = Days.valueOf("MONDAY");
monday = Days.valueOf("not even close to monday");
我也会在这里遵守枚举的约定(所有大写字母和下划线的间距,所以MONDAY
)。
最后,如果这不仅仅是一个示例问题,而且您实际上正在使用天数/日历变量等,那么默认 jdk 中已经提供了DayOfWeek
和Month
枚举。
3楼
尝试反射方式;
package com.company;
import java.lang.reflect.Method;
class Enumerations {
public enum Days {
Monday("MON"),
Tuesday("Tue");
String value;
Days(String value){
this.value = value;
}
public String getValue(){
return this.value;
}
}
public enum Months{
January("JAN"),
APRIL("APR");
String value;
Months(String value){
this.value = value;
}
public String getValue(){
return this.value;
}
}
}
public class Main {
public static void main(String[] args) throws Exception {
// know the specific class name
System.out.println(Enumerations.Months.class);
String enumName = "Days";
String value = "Monday";
// get the class by class name
Class c = Class.forName("com.company.Enumerations$" + enumName);
// new the object by value
Object o = Enum.valueOf(c, value);
// get the method by name
Method method = c.getMethod("getValue");
// invoke the method
System.out.println(method.invoke(o));
}
}