3

I have got an Enum with different values and want to switch a string variable. Now I hit a wall trying to convert the Enum values to Strings, that I can use as case constant.

My best try was to convert the Enum to a String array, but the switch doesn't seem to accept array values as a case constant. (IntelliJ says: "constant expression required")

Enum myEnum = {FOO, BAR}

String input = "foo"

final String[] constant = Arrays.stream(myEnum.values()).map(Enum::name).toArray(String[]::new); 
//converts Enum to String[]; made it final, so it is "constant" 

       switch (input) {
                    case constant[0]:
                        System.out.println("foo");
                        break;
                    case constant[1]:
                        System.out.println("bar");
                        break;
                     }

Is there an elegant way to make this switch depend on the Enum?

  • 2
    For the first it won't event compile and the second try to use `myEnum.valueOf(input.toUpperCase())`. – CodeMatrix Jun 19 '19 at 10:01
  • `String[] case` shouldn't even compile because `case` is a reserved keyword. Also note that `final` doesn't make the array a constant array. You can't reassign the array itself but you still could change the elements in that array, so `case a[0]` could actually be a `case null` etc. – Thomas Jun 19 '19 at 10:01
  • @Thomas that is just one of the things making it uncompilable – Stultuske Jun 19 '19 at 10:04
  • Assuming your input is the name of the enum values in any case you could use the solution that CodeMatrix suggested. If the input is some other property of an enum value, i.e. it doesn't match the name, you could build a `Map` and do the lookup there. Then build your switch on actual enum constants. – Thomas Jun 19 '19 at 10:05
  • @Stultuske I know, it's just the thing that bothered me most, especially that `case case[0]` (oh I missed that `switch switch`) ;) – Thomas Jun 19 '19 at 10:07

4 Answers4

4

You shouldn't convert it because it isn't needed. Also, your code won't even compile because case is a reserved keyword in Java.

You should take a look at the valueOf method of an Enum.

Your code can look like that:

public enum MyEnum {FOO, BAR}

//method
String input = "foo";
MyEnum niceFound = MyEnum.valueOf(input.toUpperCase());

That will return FOO but can throw an IllegalArgumentException when the given value isn't present as type.

CodeMatrix
  • 2,124
  • 1
  • 18
  • 30
3

You can do this :

public enum MyEnum {
    FOO("foo"),
    BAR("bar");

    private String value;

    public String getValue() {
        return value;
    }

    public static MyEnum getState(String value) {
        switch (value) {
            case "foo":
                return FOO;
            case "bar":
                return BAR;
        }
        return null;
    }

    private MyEnum(String value) {
        this.value = value;
    }
}

Now, in your class, you can :

MyEnum myEnum = getState("foo"); // returns MyEnum.FOO

Also make sure you handle the case when getState() returns null

Shrey Garg
  • 1,317
  • 1
  • 7
  • 17
  • You know you can improve that with just a for loop over the enums and check if the value is the same? That would make it more robust what your stuff isn’t for newer values. Currently you check all values per hand. Your current method is also exactly the same as the question code which just uses a switch statement. – CodeMatrix Jun 19 '19 at 10:17
  • 1
    @CodeMatrix agreed, only the thing is, if the use case requires having separate string and enum value mapping, then this way is good. – Shrey Garg Jun 19 '19 at 10:23
1

Use MyEnum.valueOf(value.toUpperCase())

public enum MyEnum {
    FOO, BAR;
}

public static void process(String value) {
    try {
        switch (MyEnum.valueOf(value.toUpperCase())) {
            case FOO :
                System.out.println("FOO");
                break;
            case BAR :
                System.out.println("BAR");
                break;
            default :
                break;
        }
    }
    catch (IllegalArgumentException e) {
        // TODO: handle exception
    }

public static void main(String[] a){
    process("foo");
}
krishna T
  • 425
  • 4
  • 14
1

A solution with Java 8+ streams would be to create a method inside your enum :

public static Optional<MyEnum> getByValue(final String value) {
   return Arrays.stream(MyEnum.values())
              .filter(myEnum -> myEnum.value.equals(value))
              .findFirst();
}

This returns optional in case there is no enum value for your String parameter. But you can change it according to your needs.

Michał Krzywański
  • 15,659
  • 4
  • 36
  • 63