繁体   English   中英

在开关上安全使用 Enum valueOf 进行字符串比较

[英]Safe use of Enum valueOf for String comparison on a switch

如果我得到一个不同于枚举ACTION支持的字符串,如何安全地实现 valueOf 的使用。 我的意思是可以强制ACTION.valueOf(valueToCompare)获得有效值,即使发生valueToCompare不是有效的枚举成员

valueToCompare"CRY""CRYALOT""cryalot"等时,我得到了预期的执行。

我在代码中的情况下得到java.lang.IllegalArgumentException

public enum ACTION{
    CRY,
    CRYALOT;
}

public static void main(String[] args) {

    String valueTocompare = "posible not expected value".toUpperCase();

    switch (ACTION.valueOf(valueToCompare)) {
        case CRY:
            System.out.println("Cry");
            break;
        case CRYALOT:
            System.out.println("Cry a lot");
            break;
        default:
            System.out.println("catch posible not expected value");
            break;
    }
}

编辑和使用解决方案:

正如@Peter Lawrey 建议的那样,我通过使用 try-catch 解决了这个问题:

public enum ACTION{
    CRY,
    CRYALOT,
    NOTVALID;
}

public static void main(String[] args) {

    String valueToCompare = "NOTVALID";
    ACTION action;
    try {
        valueToCompare= "variable posible not expected value".toUpperCase();
        action = ACTION.valueOf(valueToCompare);
    } catch(IllegalArgumentException e){
        System.out.println("Handled glitch on the Matrix");
        action = ACTION.NOTVALID;
    }

    switch (action) {
        case CRY:
            System.out.println("Cry");
            break;
        case CRYALOT:
            System.out.println("Cry a lot");
            break;
        default:
            System.out.println("catch posible not expected value");
            break;
    }

    System.out.println("We continue normal execution on main thread...");
}

您需要捕获 IllegalArgumentException

try {
    switch (ACTION.valueOf(valueToCompare)) {

    }
} catch (IllegalArgumentException iae) {
    // unknown
}

或者您可以创建自己的函数来执行此操作。

public static <E extends Enum<E>> E valueOf(E defaultValue, String s) {
    try {
        return Enum.valueOf(defaultValue.getDeclaringClass(), s);
    } catch (Exception e) {
        return defaultValue;
    }
}

注意: switch(null)抛出NullPointerException而不是分支到default:

使用异常进行流控制被认为是一种不好的做法。

    String valueToCompare = value.toUpperCase();

    ACTION action = Arrays.stream(ACTION.values())
       .filter(a -> a.name().equals(valueToCompare)).findFirst().orElse(ACTION.NOTVALID);

这里的问题是这一行: ACTION.valueOf(valueToCompare) - 您正在尝试在valueToCompare上运行valueOf ,并且由于该值不是ACTION中的枚举,因此出错。 它甚至没有使 switch 语句打印出默认的 msg。

看看我所做的更改,您会注意到一些事情,主要是 actionToCompare...

    enum Action {
      CRY,
      CRYALOT,
      EXAMPLE
    }

  public static void main(String[] args) {
    Action actionToCompare = Action.EXAMPLE;
    switch (actionToCompare) {
      case CRY:
        System.out.println("Cry");
        break;
      case CRYALOT:
        System.out.println("Cry a lot");
        break;
      default:
        System.out.println("catch posible not expected value");
        break;
    }
  }

如果您坚持使用String而不是将其转换为枚举Action ,请将其包装在try...catch语句中,以便如果传入无效字符串,它可以处理错误。

你总是可以为自己建立一个反向查找。

enum Action {
    CRY,
    CRYALOT,
    EXAMPLE;

    // Lookup map for actions in string form.
    static Map<String,Action> lookup = Arrays.stream(values()).collect(Collectors.toMap(
            // Key is name in lowercase.
            a -> a.name().toLowerCase(),
            // Value is the Action.
            a -> a));

    public static Action lookup(String name) {
        return lookup.get(name.toLowerCase());
    }
}

public void test() throws Exception {
    System.out.println(Action.lookup("cry"));
    System.out.println(Action.lookup("CryAlot"));
}

在控制流中不涉及异常并启用将枚举名称或操作名称映射到具有默认行为的操作的解决方案,以防没有映射条目:

public enum CryActions {
    CRY_A_LITTLE("Cry a little", CryALittleActionHandler::new), CRY_A_LOT("Cry a lot", CryALotActionHandler::new), DEFAULT("Default", DefaultCryActionHandler::new);

    private String actionName;
    private Supplier<CryActionHandler> supplier;

    private CryActions(String actionName, Supplier<CryActionHandler> supplier) {
        this.actionName = actionName;
        this.supplier = supplier;
        PossibleCryActions.byEnumName.put(name(), this);
        PossibleCryActions.byActionName.put(actionName, this);
    }

    public void handleAction() {
        supplier.get().handleAction();
    }

    public String getActionName() {
        return actionName;
    }

    public static CryActions fromEnumName(String enumName) {
        return PossibleCryActions.byEnumName.computeIfAbsent(enumName, x -> DEFAULT);
    }

    public static CryActions fromActionName(String actionName) {
        return PossibleCryActions.byActionName.computeIfAbsent(actionName, x -> DEFAULT);
    }

    private static class PossibleCryActions {
        private static Map<String, CryActions> byEnumName = new HashMap<>();
        private static Map<String, CryActions> byActionName = new HashMap<>();
    }
}

public interface CryActionHandler {
    void handleAction();
}

public class CryALittleActionHandler implements CryActionHandler {

    @Override
    public void handleAction() {
        System.out.println("Just crying a little...");
    }
}

public class CryALotActionHandler implements CryActionHandler {

    @Override
    public void handleAction() {
        System.out.println("Crying a river...");
    }
}

public class DefaultCryActionHandler implements CryActionHandler {

    @Override
    public void handleAction() {
        System.out.println("Just crying as default behavior...");
    }
}

public class Main {
    public static void main(String[] args) {
        CryActions.fromEnumName("CRY_A_LITTLE").handleAction();
        CryActions.fromEnumName("CRY_A_LOT").handleAction();
        CryActions.fromEnumName("CRY_UNEXPECTEDLY").handleAction();
        CryActions.fromActionName("Cry a little").handleAction();
        CryActions.fromActionName("Cry a lot").handleAction();
        CryActions.fromActionName("Cry unexpectedly").handleAction();
    }
}

科特林版本:

inline fun <reified T : Enum<T>> safeValueOf(name: String, defaultValue: T): T =
    java.lang.Enum.valueOf(T::class.java, name) ?: defaultValue

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM