4

I feel like I should be able to find an answer to this, but it turns out to be harder to search than expected... so:

In C#, when we do something like:

enum MyEnumClass { A, B };

static String Test(MyEnumClass m)
{
    switch (m)
    {
        case MyEnumClass.A: return "the value was A";
        case MyEnumClass.B: return "the value was B";
        //default: return "The value was ????"; //we need to uncomment this
    }
}

we get a "not all code paths return a value" error and need to add the default case, because enums are actually just numbers in disguise and we might be calling the method with a value we didn't cover like so:

test((MyEnumClass)53)

However, I don't think we can do such a thing (call the method with anything else than our two enum-values) in Java (Or can we?). Still, if we write similar code in Java, we get a similar error. If this is the case, is there any reason why the compiler cant figure out such a switch statement is complete and hence that the default case isn't necessary?

3 Answers 3

8

Imagine what would happen if you decided that enum needed a new value, but that enum is being used in a thousand switch statements just like that one. Because Java forced them all to have a default case when they wrote those switches, then whatever logging statement or exception throw everyone chose to put there will probably save them a lot of headaches when you make that change.

If the Java compiler accepted those thousand switch statements with only two cases because they cover all the values...then you can't ever add your third value, because nobody's code would compile anymore. And as ddyer pointed out, separate compilation makes such a check impossible in the general case.

So you're left with either always requiring a default case, or never requiring it. Since Java has a very different philosophy from C++, it chose the former.

Also, Enums in Java can be null, so you have to be prepared for that.

9
  • 4
    enums can not only be null, but switch(enum) will get a null pointer exception if it is.
    – ddyer
    Mar 11, 2015 at 20:52
  • 4
    Likewise, because classes are compiled independently, the enum class can be extended and recompiled long after the switch was compiled, which could create an undefined result if there were no default clause in the switch.
    – ddyer
    Mar 11, 2015 at 21:02
  • Couldn't one argue that having to explicitly add all those thousands of switch-cases is analogous to having to remove all the switch-cases like you have to do when you remove an enum-value? Also, good point point about nulls and thanks for the reply!
    – Hirle
    Mar 11, 2015 at 21:04
  • 1
    @Hirle Sort of, except the rule forcing you to add a default case is enforced when you first write the switches, and that makes it possible to add values to the enum in a backwards compatible way, while removing an enum value that people have used is always going to be backwards-incompatible (and thus something you should avoid). We might be thinking of different arguments though.
    – Ixrec
    Mar 11, 2015 at 21:08
  • 1
    @Ixrec I don't think we are thinking about different arguments, and I think I see your point a bit more clearer now. Rephrasing this bit (for my own understanding): My analogy between adding and removing enumvalues doesn't hold, because values being added as code evolves is something that the language is designed to handle (in fact, this is part of the design in the language that handles it), while the language is NOT designed to handle values being removed (it isn't designed to handle values being removed because that is something you plain shouldn't do). Right?
    – Hirle
    Mar 11, 2015 at 21:18
2

With Java 17+ you can use the new switch syntax to ensure that you covered all cases:

private String getMyEnumClassDescription(MyEnumClass m) {
    return switch (m) {
        case A -> "the value was A";
        case B -> "the value was B";
    };
}

However, in this case it is better to put the string value into enum, so switch is not needed at all.

1

The reason the compiler will prompt "not all code paths return a value" is because it notices that your switch case does not cover all of the possibilities. This is NOT a restriction on the type of object you are using a switch on. If you return a value in the default case, the compiler reads it as a way of handling the case for other possible values.

Another option is to add a return statement after the switch statement.

1
  • 2
    Actually, adding a return statement after the switch statement is my preferred way as it gives me a warning when the enum gets extended.
    – maaartinus
    Apr 6, 2015 at 3:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.