【问题标题】:How do I switch on values defined inside a java enum of strings如何打开在 Java 字符串枚举中定义的值
【发布时间】:2016-09-05 18:24:43
【问题描述】:

我有以下代码:

class MyClass {
    private Value value;
    public enum Value {
        INSERT_ONLY("INSERT_ONLY"), UPDATE_ONLY("UPDATE_ONLY"), UPSERT("UPSERT") ;
        private final String val ;
        private Value(final String v) {val = v ;}
        public String toString() {return val ;}     
        public String getVal() {
            return val;
        }
    } ;
    public Value getValue() {
        return value;
    }
    public void setValue(Value value) {
        this.value = value;
    }
}

public class one {
    public static void main(String[] args) {
        MyClass obj = new MyClass() ;
        obj.setValue(MyClass.Value.INSERT_ONLY) ;

        String s = obj.getValue().toString() ;
        String s1 = MyClass.Value.INSERT_ONLY.toString() ;
        switch(s) {
            case "INSERT_ONLY" : System.out.println("INSERT_ONLY") ;
                break ;
            case "s2" : System.out.println("s2") ;
                break ;
        }
    }
}

此代码有效。但我想要的是在 switch-case 中我使用enum Value 中定义的字符串。如果我在case 中使用s1,则会产生错误。出路是什么?

【问题讨论】:

  • 您使用的是哪个版本的 Java?什么错误?
  • 我想在case 中使用s1 而不是在switch 中使用

标签: java enums switch-statement


【解决方案1】:

枚举有一个方法.name(),它将枚举作为字符串返回。您所有的“价值观”都与此等效-只需打开它即可。

您可以删除value 字段、构造函数和getter,然后在当前调用getValue() 的位置调用name()

此外,toString() 的默认实现返回 name(),因此您可以删除您的 toString() 方法而不会产生任何影响。

最后,您可以打开枚举本身。

【讨论】:

    【解决方案2】:

    你在枚举中的字符串其实和枚举常量是一样的……所以有点多余,完全没必要……

    试试这个:

    enum Value {
        INSERT_ONLY, UPDATE_ONLY, UPSERT;
    }
    
    public static void main(String[] args)  {
    Week obj = new Week() ;
    Value s = obj.getValue( ) ;
            switch(s) {
                case INSERT_ONLY : System.out.println("INSERT_ONLY") ;
                    break ;
                case UPDATE_ONLY : System.out.println("UPDATE_ONLY") ;
                    break ;
            }
        }
    }
    

    【讨论】:

    • 我需要这些字符串,因为我必须最终将 MyClass 的对象来回转换为 json 对象
    • 如果调用方法 name(),该枚举的每个常量都可以打印为字符串
    【解决方案3】:

    你可以这样试试:

    MyClass.Value value = obj.getValue() ;
    switch(value) {
      case INSERT_ONLY : System.out.println("INSERT_ONLY") ;
        break ;
      case UPSERT : System.out.println("Upsert") ;
        break ;
      case UPDATE_ONLY : System.out.println("Update only") ;
       break ;
     }
    

    基本上,switch 语句使用枚举名称。所以不需要对obj.getValue()返回的Value应用toString()-方法。

    如果您想知道为什么 switch 不能与字符串结合使用,请查看here。 还有一个建议:将默认分支也添加到 switch 语句中。

    【讨论】:

      【解决方案4】:

      如果我理解正确,您正在尝试通过未知字符串 s 查找枚举常量。您的case 表达式不能是s1 的原因是因为它必须是compile-time constant,而s1 不是。由于您的示例似乎主要是理论上的,因此我会建议一些选项,您可以选择最适合您的实际情况的选项:

      1. 假设枚举名称与其values 相同(在这种情况下,您可以完全废弃该字段)并且您只是试图通过其名称查找枚举,只需执行以下操作:

        MyClass.Value v = MyClass.Value.valueOf(s);
        

        如果没有找到s1 的映射,这将抛出一个IllegalArgumentException

      2. 仍然假设名称相同,但您确实需要一个实际的 switch 以及一些额外的案例和自定义逻辑:

        try {
            MyClass.Value v = MyClass.Value.valueOf(s);
            switch (v) {
                case INSERT_ONLY : System.out.println("INSERT_ONLY") ;
                    break ;
            }
        } catch (IllegalArgumentException e) {
            switch (s)
                case "s2" : System.out.println("s2") ;
                    break ;
            }
        }
        
      3. 如果名称实际上不一样,可以在枚举类中添加静态常量映射,模拟valueOf()

        public enum Value {
            ONLY_INSERT("ONLY_INSE"), ONLY_UPDATE("UPDATE_ONLY"), UPSERT("UPSERT") ;
        
            private static final Map<String, Value> byName = new HashMap<>();
            static {
                for (Value v : values()) {
                    byName.put(v.getVal(), v);
                }
            }
        
            public static Value byName(String name) {
                Value result = byName.get(name);
                if (result == null) {
                    throw new IllegalArgumentException("Invalid name" + name);
                }
                return result;
            }
        
            private final String val ;
            private Value(final String v) {val = v ;}
            public String toString() {return val ;}     
            public String getVal() {
                return val;
            }
        } ;
        

        现在您可以使用MyClass.Value.byName() 执行与之前的解决方案相同的操作。

      【讨论】:

        猜你喜欢
        • 2012-01-25
        • 2021-12-23
        • 2020-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-10
        • 2013-07-03
        相关资源
        最近更新 更多