I agree with the answer of @JBNizet. However, maybe not in all cases you would want an exception for something that cannot occur.
I acknowledge that this is probably a little different scenario than what the OP intended, but I think still helps to put the correct answer in a broader context.
See below example.
public class App {
enum Which {ONE, TWO};
String on(Which which) {
switch (which) {
case ONE: return "This is one";
case TWO: return "This is another";
default: throw new IllegalStateException("Missing case: "+which.name()+" of Which");
}
}
}
Suppose that someone adds a 3rd Enum value THREE
. This code will always compile fine, and the Editor (Netbeans / Eclipse) will also never flag this as a problem. You will only get that there is an issue during run-time.
In this case, I would even propose making sure that there is no default
case defined that explicitly throws an exception. If chosen the right settings in javac or editor, it would at least be flagged much earlier. In the worst case, it would compile, but at run-time, you would still get a RuntimeException:
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - missing return statement
A little dubious ... 'Uncompilable' during runtime ...
This only works for bound switch set's that the compiler or editor should be able to figure out, meaning only Enum, and not String or int. For those cases, I likely would recommend still putting an explicit exception for uncovered case's.
Ah - and also, I am bound to say that switch cases can be avoided in a lot of scenario's ... Either by binding the case directly as a method to the Enum value (override an abstract method), or by implementing a visitor pattern.
Here is how the enum could have been re-implemented:
public class App {
enum Which {
ONE { @Override String on() { return "This is One"; } },
TWO { @Override String on() { return "This is Two"; } },
THREE { @Override String on() { return "This is Three"; } },
;
abstract String on();
};
static String on(Which which) {
return which.on();
}
public static void main(String[] args) {
String result = on(Which.THREE);
}
}
Now we have completely avoided this whole scenario ... It will now always come down to an unimplemented method detected at compile-time! Plus it is much faster too, as no switch/case lookup has to happen.
That is probably what the end-goal should be:
Prefer Compile Time Errors over Runtime Exceptions.