简体   繁体   English

如何打开在Java字符串枚举中定义的值

[英]How do I switch on values defined inside a java enum of strings

I have the following code : 我有以下代码:

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 ;
        }
    }
}

This code works. 此代码有效。 But what I want is that in switch-case I use the strings as defined in the enum Value . 但是我想要的是在切换情况下,我使用enum Value定义的字符串。 If I use s1 in case , it generates an error. 如果在case使用s1 ,它将生成错误。 What is the way out? 出路是什么?

Enums have a method .name() that returns the enum as a String. 枚举有一个方法.name() ,它以字符串形式返回枚举。 All your "values" are equivalent to this - just switch on that. 您所有的“值”都与此等效-只需打开它即可。

You can delete the value field, the constructor and getter and call name() where you are currently calling getValue() . 您可以删除value字段,构造函数和getter,并在当前调用getValue()地方调用name() getValue()

Further, the default implementation of toString() returns name() so you can delete your toString() method without having any effect. 此外, toString()的默认实现返回name()因此您可以删除toString()方法而不会产生任何影响。

Finally, you can switch on the enum itself. 最后,您可以打开枚举本身。

you string in the enum is actually the same as the enumertor constants... so it is a little redundant and completely unnescessary... 您在枚举中的字符串实际上与枚举器常量相同...因此有点多余,完全没有必要...

try this: 尝试这个:

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 ;
        }
    }
}

You could try it this way: 您可以这样尝试:

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 ;
 }

Basically, the switch-statement uses the enum-names. 基本上,switch语句使用枚举名称。 So there is no need to apply the toString() -method on the Value returned by obj.getValue() . 因此,无需在obj.getValue()返回的Value上应用toString()方法。

If you would like to know why switch will not work in combination with strings, please have a look here . 如果您想知道为什么switch不能与字符串结合使用,请在此处查看 One more suggestion: add also the default-branch to the switch-statement. 另一个建议:在switch语句中也添加default分支。

If I understand correctly, you're trying to look up an enum constant by an unknown string s . 如果我理解正确,则您正在尝试通过未知字符串s查找枚举常量。 The reason your case expression can't be s1 is because it must be a compile-time constant , which s1 is not. 您的case表达式不能为s1的原因是,它必须是一个编译时常量 ,而s1不是。 Since your example seems to be mostly theoretical, I'll suggest a few options and you can pick the most appropriate for your actual case: 由于您的示例似乎主要是理论上的,所以我将建议一些选择,您可以根据实际情况选择最合适的选择:

  1. Assuming the enum names are the same as their value s (in which case you can scrap the field entirely) and you're just trying to look up an enum by its name, just do this: 假设枚举名称与其value s相同(在这种情况下,您可以完全废弃该字段),而您只是想按其名称查找枚举,只需执行以下操作:

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

    This will throw an IllegalArgumentException if no mapping is found for s1 . 如果未找到s1映射,则将抛出IllegalArgumentException

  2. Still assuming the names are the same, but you do need an actual switch with some additional cases and custom logic: 仍然假设名称相同,但是您确实需要带有一些其他情况和自定义逻辑的实际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. If the names are not actually the same, you can add a static map of constants inside the enum class, to simulate valueOf() : 如果名称实际上不同,则可以在enum类内添加常量的静态映射,以模拟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; } } ; 

    Now you can do the same as the previous solutions, using MyClass.Value.byName() . 现在,您可以使用MyClass.Value.byName()与以前的解决方案相同。

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

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