168

Why can't you switch on an enum in Java? It seems simple enough to do and would make for some convenient code. Also this question could apply to String's. You can switch on a char, but not a String ...?

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
user663321
  • 1,963
  • 2
  • 14
  • 10
  • 14
    Show us your non-working enum switch code. – Steve Kuo Jun 17 '11 at 21:10
  • 1
    Why duplicate flags, look at how precise is the heading, easy to find for new users. – Indigo Aug 19 '14 at 13:01
  • You can take a look at this article to see how it's done: http://www.tutorialspoint.com/javaexamples/method_enum.htm – IgorGanapolsky Sep 10 '14 at 14:04
  • "It seems simple enough to do and would make for some convenient code." Yes Java is simple but convenient Java isn't! The REAL SIMPLE way of doing switch-statement is like it is in C and Java does it this way! On principle Java isn't convenient like C# is itended to. This is the Java way of life. You have to deal with this mentality if you realy want to code in Java. – Stelzi79 Apr 30 '16 at 20:58
  • 1
    You got this error because you are trying to type in the case enumName.Value You have to type switch(enumVariable) {case value:} – Moaz Rashad Nov 15 '18 at 11:21
  • Since Java 8 you can use Strings on a Switch statement. – Hola Soy Edu Feliz Navidad Sep 16 '19 at 09:12
  • FYI, this may get better in future versions of Java. See: [*JEP 406: Pattern Matching for switch (Preview)*](https://openjdk.java.net/jeps/406). – Basil Bourque Apr 10 '21 at 22:09

6 Answers6

289

You definitely can switch on enums. An example posted from the Java tutorials.

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 
    THURSDAY, FRIDAY, SATURDAY 
}

public class EnumTest {
    Day day;

    public EnumTest(Day day) {
        this.day = day;
    }

    public void tellItLikeItIs() {

        switch (day) {
            case MONDAY: 
                System.out.println("Mondays are bad.");
                break;

            case FRIDAY: 
                System.out.println("Fridays are better.");
                break;

            case SATURDAY:
            case SUNDAY: 
                System.out.println("Weekends are best.");
                break;

            default:
                System.out.println("Midweek days are so-so.");
                break;
        }
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
CoolBeans
  • 20,654
  • 10
  • 86
  • 101
  • 8
    Beautiful example that answers the question very well. That said, I've been programming Java for 14 years and I don't remember a single case where I kept a switch statement in production code. When a switch statement would be better than a series of if/else, I have always written an instance method on my enum instead along the lines of what Josh Bloch suggests. In my `Day` enum, I add `public string tellItLikeItis() { return "Midweek days are so-so."; }` then have `MONDAY`, `FRIDAY`, `SATURDAY`, and `SUNDAY` override that method. – GlenPeterson Jun 19 '14 at 15:44
  • Which is to say that I do it as @GregMattes suggests in the second-most-popular answer. – GlenPeterson Jun 19 '14 at 15:46
  • 6
    @GlenPeterson FYI if you're trying to optimize for speed, the switch statement approach might be faster because it's just a table lookup in the bytecode. With your approach, you have to push a new function onto the stack. It's a micro-optimization, but if speed is super important it's something to keep in mind. – Byte Lab Feb 12 '16 at 21:19
  • 2
    @GlenPeterson, that assumes you're compiling the enum code yourself, which is obviously not always the case. – aioobe Aug 04 '16 at 04:28
89

You actually can switch on enums, but you can't switch on Strings until Java 7. You might consider using polymorphic method dispatch with Java enums rather than an explicit switch. Note that enums are objects in Java, not just symbols for ints like they are in C/C++. You can have a method on an enum type, then instead of writing a switch, just call the method - one line of code: done!

enum MyEnum {
    SOME_ENUM_CONSTANT {
        @Override
        public void method() {
            System.out.println("first enum constant behavior!");
        }
    },
    ANOTHER_ENUM_CONSTANT {
        @Override
        public void method() {
            System.out.println("second enum constant behavior!");
        }
    }; // note the semi-colon after the final constant, not just a comma!
    public abstract void method(); // could also be in an interface that MyEnum implements
}

void aMethodSomewhere(final MyEnum e) {
    doSomeStuff();
    e.method(); // here is where the switch would be, now it's one line of code!
    doSomeOtherStuff();
}
Greg Mattes
  • 33,090
  • 15
  • 73
  • 105
  • 3
    One of the nice things about this approach is that it is simply impossible to get certain types of errors. You can't miss a switch case (you can incorrectly implement a method for a particular constant, but there's nothing that will ever totally prevent that from happening!). There's no switch "default" to worry about. Also, I've seen code that puts enum constants into arrays and then indexes into the arrays - this opens the possibility of array index out of bounds exceptions - just use the enum! Java enums are very, very powerful. Learn all that you can about them to use them effectively. – Greg Mattes Jun 18 '11 at 15:01
  • 2
    Also note if you have several enum constants that all have the same behavior for a particular method (like @CoolBeans days of the week example in which weekend days have the same behavior and the weekdays Tuesday through Thursday also share the same behavior), you can simply gather that shared code in an enum method that is not overridden by every constant (final protected) and then call that method from the appropriate methods. So, in my example I could add "final protected void commonMethod() { ... }" and then the implementation of method() in each constant would just call commonMethod(). – Greg Mattes Jun 18 '11 at 15:09
  • Now that this question has been closed as a duplicate, I notice that one of the duplicates has an answer quite (perhaps eerily) similar to mine: http://stackoverflow.com/questions/2663980/why-do-i-get-an-enum-constant-reference-cannot-be-qualified-in-a-case-label/2667671#2667671 - Scout's honor: I didn't know about his answer before I wrote mine! – Greg Mattes Jun 18 '11 at 15:58
  • :-). This question ended up being a _train-wreck_. – CoolBeans Jun 18 '11 at 17:10
  • 4
    Why? Because it's a duplicate? It happens, no big deal. Maybe the information will be merged someday. You learned something, right? Somebody else probably did too. That alone makes it valuable. – Greg Mattes Jun 20 '11 at 01:03
27

Article on Programming.Guide: Switch on enum


enum MyEnum { CONST_ONE, CONST_TWO }

class Test {
        public static void main(String[] args) {
            MyEnum e = MyEnum.CONST_ONE;

            switch (e) {
                case CONST_ONE: System.out.println(1); break;
                case CONST_TWO: System.out.println(2); break;
            }
        }
    }

Switches for strings are implemented in Java 7.

aioobe
  • 413,195
  • 112
  • 811
  • 826
26

First, you can switch on an enum in Java. I'm guessing you intended to say you can’t, but you can. chars have a set range of values, so it's easy to compare. Strings can be anything.

A switch statement is usually implemented as a jump table (branch table) in the underlying compilation, which is only possible with a finite set of values. C# can switch on strings, but it causes a performance decrease because a jump table cannot be used.

Java 7 and later supports String switches with the same characteristics.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Michael Lowman
  • 3,000
  • 1
  • 20
  • 34
17

You might be using the enums incorrectly in the switch cases. In comparison with the above example by CoolBeans.. you might be doing the following:

switch(day) {
    case Day.MONDAY:
        // Something..
        break;
    case Day.FRIDAY:
        // Something friday
        break;
}

Make sure that you use the actual enum values instead of EnumType.EnumValue

Eclipse points out this mistake though..

aioobe
  • 413,195
  • 112
  • 811
  • 826
brayne
  • 1,355
  • 2
  • 16
  • 27
  • +1 However I found that when you assign, you must use day = Day.Monday; Otherwise I was getting a 'cannot find symbol' compile error. – likejudo Dec 27 '12 at 21:03
2

Actually you can use a switch statement with Strings in Java...unfortunately this is a new feature of Java 7, and most people are not using Java 7 yet because it's so new.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131