views:

76

answers:

3

From time to time I have to add a new value to a enum type in my project.

public enum Day {
  SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, 
   FILENOTFOUND //this one is new one
}

What I would like is to have a compile time error for every switch I have that is not treating the new value, like this one:

switch (color) {
        case MONDAY: 
        case TUESDAY: 
        case WEDNESDAY: 
        case THURSDAY: 
                    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;
    } 

Having a default: that throws some exception is not good enough, I would like it to be compile time.

I don't think this is possible but maybe someone has a neat trick...

I thought Findbugs would have a rule to find those but I only saw this: Eq: Covariant equals() method defined for enum (EQ_DONT_DEFINE_EQUALS_FOR_ENUM)

EDIT: I'm choosing Mark's reply, I do use Eclipse and that sounds just like what I needed! I am not an expert in findbugs at all so I might have missed such functionality, though I don't think so.

+4  A: 

Eclipse has a compile-time warning/error you can enable: Enum constant not covered on "switch".

From your Project properties (or general preferences), go to Java Compiler->Errors/Warnings , check Enable project specific settings. You'll find the warning under Potential programming problems. It's set to Ignore by default but you can bump it up to Warning or Error.

Edit: I thought this goes without saying but I suppose I'll say it anyway: this is only applicable if you're developing in Eclipse or using it for your build management. Obviously a Findbugs or similar equivalent would be the "real" answer since it transcends the IDE and can be integrated into the build process.

Mark Peters
That's a nice feature but it won't help on existing switches on the enum you are adding a new value to.
rsp
@rsp: Yes it does. If you go back and edit the enum, adding a new value, it will generate warnings/errors over all switch statements that use that enum.
Mark Peters
It does surprise me that Eclipse would have this while Findbugs doesn't.
Mark Peters
@Mark Peters, yes, for code in the same project, how about code in projects using your enum from a library.jar?
rsp
@rsp: What about them? If they're compiled through eclipse, this will catch them. If they're not under your control, obviously you can't catch those errors but then neither will anything else. E.g. if it's a distributed library jar, do you expect to see error messages from all 800,000 clients that use your jar? Obviously you need control of your jar to find it. He asked for a compile error, **which implies he's compiling it**.
Mark Peters
@Mark Peters, my point is that an IDE feature does not make the cient code containing switches on enums robust against changes unless they are recompiled against the new version. It does help when the client code logs unhandled cases.
rsp
@rsp: Sure, but that's not what the OP asked for. He asked for a compile-time error which obviously implies he's going to be recompiling the client code.
Mark Peters
I like to think we are also here to help people create better code, even if the advice is not what they asked for exactly.
rsp
+1  A: 

You could do that by adding a default clause and logging when it is visited:

switch (color) {
default:
    log.error("Unknown color in switch: " + color);
    break

case MONDAY: /*FALLTHROUGH*/
case TUESDAY: 

(adding fallthrough comments help later maintainers to decide whether you forgot code or not :-))

Edit Clarification copied from comments on Mark's answer:

An IDE feature signalling cases like this is fine for the developer at the moment of the change but it does not catch changes in other parts of code that your code depends on.

It does not make the cient code containing switches on enums robust against changes unless they are recompiled against the new version.

It does help when the client code logs unhandled cases; deployed code does not always have full control over its classpath or the versions of libraries on it.

rsp
@rsp, this is a compile-time check as the OP requested?
Kirk Woll
Not compile-time so limited in use and unapplicable to the question. Edit: removed d/v, this is still useful so I can't call it "wrong".
Mark Peters
@Kirk Woll, no it isn't. Using this pattern makes your code more robust against changes to used classes/enums even if you don't recompile the code containing the switch. As I see it is is a better alternative to make sure you don't miss this kind of situation even if your IDE does support this type of check.
rsp
@rsp: If runtime is the route this might be a good candidate for an assert or similar; something that can be removed when building production code.
Mark Peters
@Mark, part of my point is that checks like these should be present in production code, not just during the development / test / acceptance phases.
rsp
A: 

IntelliJ was a check where not all case have been set. It has an auto-fix to fill in the missing cases.

Peter Lawrey