6

Suppose you have an enum with 3 values:

enum Colors { RED, GREEN, BLUE }

You switch over all values of it in some method, thinking you've handled all cases:

switch (colors) {
    case RED: ...
    case GREEN: ...
    case BLUE: ...
}

Then later, you add a new value to the enum:

enum Colors { RED, GREEN, BLUE, YELLOW }

And everything still compiles fine, except you're silently missing a case for YELLOW in the method. Is there a way to raise a compile-time error in such a scenario?


edit: Do not understand why this was marked a dupe of Can I add and remove elements of enumeration at runtime in Java. Since the answer there was "no", that means it should be possible to know at compile-time all values of an enum, and therefore what I'm asking for should be possible for the compiler/some code analysis tool to implement, right?

James Ko
  • 32,215
  • 30
  • 128
  • 239

3 Answers3

8

No. But enums are classes. So you can use polymorphism:

enum Color { 
    RED {
        @Override
        public void foo() { ... }
    },
    GREEN {
        @Override
        public void foo() { ... }
    },
    BLUE {
        @Override
        public void foo() { ... }
    };

    public abstract void foo();
}

Now, if you add a color, the compiler won't let you add it it it doesn't override the abstract method.

And instead of

switch (color) {
    case RED: ...
    case GREEN: ...
    case BLUE: ...
}

you can just use

color.foo();

Note that Kotlin allows to do what you want, if Kotlin is an option.

Also note that BLUE is a color, not a colors. So the enum should be named Color, not Colors.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thumbs up for mentioning Kotlin here! – Michael Piefel Sep 10 '17 at 18:41
  • Exactly, replacing conditionals with polymorphism is the OOP way to solve this. – Mick Mnemonic Sep 10 '17 at 18:41
  • This is a really, really intriguing answer. I'm not sure I want to put logic in my `Colors` enum though, haha :) This is essentially turning the enum into an interface. – James Ko Sep 10 '17 at 18:48
  • 2
    You can use the visitor pattern to use polymorphism while still leaving logic out of the enum. But if you can't modify the enum, there's nothing you can do except having an exception at runtime, unit tests, or use a language whose compiler makes that check. – JB Nizet Sep 10 '17 at 18:52
6

That depends on the compiler. The Eclipse IDE built-in compiler can be configured to raise an error in that case.

Windows/Preferences Java Compiler Errors/Warnings "Incomplete 'switch' cases on enum" can be set to "Error".

EDIT:

There even is a sub-option "signal even if 'default' case exists".

Ralf Kleberhoff
  • 6,990
  • 1
  • 13
  • 7
1

I don't think there is a default way of doing this. It might be possible with some external tools.

Why not providing a default in the switch statement and raising an Exception. Besides, you should have enough unit tests to test this scenario, if you compile your project and all you unit tests are ok, this would mean you aren't testing deep enough.

Joey Reinders
  • 119
  • 2
  • 6
  • That’s possibly a _lot of_ work that really should be left to the compiler. (Of course, in Java you can’t, which is a shame.) Your reasoning about using tests for such checks could be applied in a much broader sense; so why do we have types and stuff and any compile-time checks at all? – Michael Piefel Sep 10 '17 at 18:40