During a recent code review I was asked to put default
cases in all the files wherever switch
block is used, even if there is nothing to do in default
. That means I have to put the default
case and write nothing in it.
Is this the right thing to do? What purpose would it serve?
-
9Its up to your... I mean supervisor's code style.S.D.– S.D.2013年01月04日 16:01:20 +00:00Commented Jan 4, 2013 at 16:01
-
1I think there are even cases where you don't want a default case. Consider switching over an enum. Your switch defines a case for all possible values. Now adding a value to an enum should result in adding a case in that switch. If you didn't do so, this might be an error, since you want to do something for this new enum value, but your code doesn't. Your compiler can warn you (I think; not sure about Java) about that, but only if you did not put a default case. Alternatively, you could print a warning in the default case when you're sure the code never reaches it.leemes– leemes2013年01月05日 03:29:25 +00:00Commented Jan 5, 2013 at 3:29
-
6Me and my friends call this the "Developer Exception" case -- when something in the code happens that you know should never happen (because of logical/code reasons), then we add a "Developer Exception" that's thrown. That way, if this ever does happen, a Developer Exception is thrown and at least we know where things went seriously wrong.Marco– Marco2013年01月08日 20:32:29 +00:00Commented Jan 8, 2013 at 20:32
8 Answers 8
It seems there are three cases when a default
statement is not necessary:
no other cases are left, because there is a limited set of values that enter the
switch case
. But this might change with time (intentionally or accidentally), and it would be good to have adefault case
if anything changes _ you could log or warn the user about a wrong value.you know how and where the
switch case
will be used and what values will enter it. Again, this might change and an extra-processing might be needed.other cases do not need any special processing. If this is the case, I think you are asked to add a
default case
, because it is an accepted coding style, and it makes your code more readable.
The first two cases are based on assumptions. So (assuming you work in not-so-small team since you have regular code reviews), you cannot afford making those assumptions. You don't know who will be working with your code or making calls to functions/invoking methods in your code. Similarly, you might need to work with someone else's code. Having the same coding style will make it easier to deal with someone's (including your) code.
-
16In case 1 and 2, a default case should be an error. If your coding style always use default, then do that, but make it emit an error in 1 and 2. Is possible, it should emit it at compile time, but that might not always be possible, if ever in java. I at least think it's important for the user to get the message that "You are shooting yourself in the foot by passing in this value"martiert– martiert2013年01月04日 07:33:31 +00:00Commented Jan 4, 2013 at 7:33
-
11A default case is always a good idea, because, for example in the case of an enum, if someone adds a new entry to the enum, your default case should do something similar to
throw new IllegalStateException("Unrecognised case "+myEnum)
which shows you where and what the error is.Rich– Rich2013年01月04日 10:34:40 +00:00Commented Jan 4, 2013 at 10:34 -
Does this mean you should always have an
else
clause after everyif/else if
even if you know that shouldn't happen? Doesn't seem like a good idea to me...jadkik94– jadkik942013年01月09日 22:31:07 +00:00Commented Jan 9, 2013 at 22:31 -
2If I may add an anecdote from my work: I had a factory method that used an enum to instantiate some classes. I had left instructions that whenever you added a new class to that project you have to add a value to the enum and a case o the switch. Of course, a week after I closed the code it stops working, with one of the exceptions that must never be raised. I go over to the programmer and ask him: "did you add a case to the switch?" and surely enough, he didn't. At that day I changed the exception to say "if you get this message, blame the last developer who touched the code".Ziv– Ziv2013年01月14日 15:03:22 +00:00Commented Jan 14, 2013 at 15:03
Is this the right thiong to do? What purpose would it serve ?
It's not uncommon for company coding standards to require a default case for all switch
statements. One reason for it is that it makes it easy for readers to find the end of the switch
. Another, probably better reason is that it makes you think for a second about what your code should do when the condition doesn't match your expectations. Regardless of the reason for the requirement, if it's a company standard, you should follow it unless there's an airtight reason not to.
If you believe that your switch
includes cases for every possible condition, then a good thing to do is to put an assert
statement in the default case. That way, when someone changes the code and inadvertently adds a condition that your switch
doesn't cover, they'll hit the assert
and realize that they need to address that part of the code.
If your switch
only covers a few of the possible conditions, but nothing special has to be done for the others, you can leave the default case empty. It's a good idea to add a comment in that case to indicate that the default case is intentionally empty because the conditions that hit it don't need any work to be done.
-
1
-
1@FLY It's a keyword in Java and usually a macro in C, C++, etc. Either way, an assert is used to test that some assumption remains true and throw and exception or otherwise cause an error if it's not.Caleb– Caleb2013年01月04日 16:14:58 +00:00Commented Jan 4, 2013 at 16:14
-
I've edited my previous comment with a link to the wikipediaFLY– FLY2013年01月07日 14:01:05 +00:00Commented Jan 7, 2013 at 14:01
-
You should not leave an empty case. If your switch doesn't cover all possible conditions you should assert the other conditions in your default case for the same reason you suggested to add an assert in the default case in your second paragraph.rold2007– rold20072013年01月07日 21:41:23 +00:00Commented Jan 7, 2013 at 21:41
If you "switch" on pure enumeration type, it is dangerous to have default fallback. When you later add values to enumeration type, compiler will highlight switches with new values not covered. If you have default clause there, compiler will stay silent, and you may miss it.
-
2+1 for catching the problem at compile-time and not at run-time.SylvainD– SylvainD2013年01月04日 10:20:10 +00:00Commented Jan 4, 2013 at 10:20
-
I wonder how completely misleading answer is voted and accepted. Quick googling shows that java compiler has such sort of warning. Why on earth will you wait for error at runtime, folks?Artur– Artur2013年01月04日 19:56:25 +00:00Commented Jan 4, 2013 at 19:56
-
I did not know about this behaviour. My ideone code sample ideone.com/WvytWq suggests otherwise. Assuming you say is true, what happens if someone adds values to an enumeration type, but you do not recompile your code?emory– emory2013年01月05日 03:32:55 +00:00Commented Jan 5, 2013 at 3:32
-
stackoverflow.com/questions/3999942/…Artur– Artur2013年01月05日 12:09:13 +00:00Commented Jan 5, 2013 at 12:09
-
1Obviously, new values are just not handled by switch statement without default case. But if you do not recompile your implementations when interfaces change, your build system is really broken.Artur– Artur2013年01月05日 12:11:59 +00:00Commented Jan 5, 2013 at 12:11
In many respects, this question is the same as the often asked Do I need an else
clause at the end of an if
/else if
ladder that covers every option.
The answer is, syntactically speaking, no you don't. But there is a however...
A default
clause can be there for (at least) two reasons:
- As an error handler - sure, Should never get here! is a claim that can be made, but What if it does? Data corruption, or even worse, no data validation are routes to program failure if not properly trapped. In this case, it shouldn't be an empty clause!
- Design/Code Coverage - even in the simplest form of a flow-chart, there are two routes from an if-statement, and always an
otherwise
from a case. There is no reason whatsoever for not including these in the source code.
My philosophy is always quite simple - assess the worst case scenario of the two options, and go for the safest. In the case of an empty else
or default
clause, the worst case options are:
- Include them: An extra three or four lines of "redundant" code.
- Do Not Include Them: Rogue data or an unexpected condition is not trapped, potentially causing program failure.
Overdramatic? Maybe... but then my software has the potential of killing people if it goes wrong. I'd rather not take that risk.
As an aside, the MISRA-C guidelines {see profile for affiliation} recommend a default
clause for every switch
-
Not only at the end of a ladder. The question is: do I need an
else
after anif
. But as you said, no, it's not.ott--– ott--2013年01月04日 20:16:05 +00:00Commented Jan 4, 2013 at 20:16 -
As an error handler, I suggest a slightly modified form that avoids the empty default. As for killing people, I don't think it actually matters - the people will be just as dead whether or not you have the default clause, but it will make it easier to figure out why they died.emory– emory2013年01月05日 03:16:29 +00:00Commented Jan 5, 2013 at 3:16
-
Good point, @emory - that wasn't very clear, was it... edited :)Andrew– Andrew2013年01月05日 07:13:23 +00:00Commented Jan 5, 2013 at 7:13
Java doesn't force you to have a 'default' statement but it is good practice to have one all of the time, even if the code may never be reached (right now). Here's a few reasons:
By having an unreachable default clause you show the reader of your code that you considered the values and know what you are doing. You also allow for future changes, say for example: a new enum value is added the switch shouldn't silently ignore the new value; you can throw an Exception there instead or do something else.
To catch an unexpected value (in case you aren't switching on an enum) that is passed in - it might be greater or less than what you expected, for example.
To handle 'default' actions - where the switches are for special behaviour. For example, a variable might be declared outside of the switch but not initialised and each case initialises it to something different. Default in this case could initialise it to a default value so the code immediately after the switch doesn't error/throw an exception.
Even if you decide to put nothing in the default (no exceptions, logging, etc.) then even a comment to say that you've considered the fact default will never occur may help readability of your code; but that comes down to personal preference.
I would also add that it depends on the philosophy of the language you are using. In Erlang for example, where it is a common approach to 'let it crash', you would not define a default case but let your case
statement raise an error if a situation occurs that was not catered for.
You should always have a default unless you have provably and permanantly covered all cases. It costs nothing, and it's insurance against failure to maintain your switch statement in an evolving program.
If you're really sure you don't care about any other cases, the default: break;//don't care but the default default should be something like default: throw new Error("unexpected value");
Likewise, you should never "drop through" a nontrivial case construct without adding a comment to the effect that you intend to drop through. Java got this one wrong at the design stage.
Consider
enum Gender
{
MALE ,
FEMALE ;
}
and
void run ( Gender g )
{
switch ( g )
{
case MALE :
// code related to males
break ;
default :
assert Gender . FEMALE . equals ( g ) ;
// code related to females
break ;
}
}
I would argue that this is superior to having a MALE case, a FEMALE case, and a default case that throws an exception.
During your testing phase, the computer will check if g is FEMALE. During production, the check will be omitted. (Yeah a microoptimization!)
More importantly, you will maintain your goal of 100% code coverage. If you wrote a default case that throws an Exception, how would you ever test it?
-
11. No need for microoptimalization - dead code elimination is used in compilers for past 30 years or so and it will be eliminated by JIT. 2. 100% code coverage is usually not considered important (on one hand 100% coverage might not catch all edge cases, on another no test will catch assert_not_reached lines on correct program). In this case leaving no default case would cause compiler error. On the other hand - how would you check if the assert works (you shift the problem and hide it by 100% coverage instead of having the same line 'it won't happen, I promise').Maja Piechotka– Maja Piechotka2013年01月05日 10:52:08 +00:00Commented Jan 5, 2013 at 10:52
-
13. When does
Gender . FEMALE . equals ( FEMALE ) ;
evaluate tofalse
? You meantGender.FEMALE.equals (g)
but since you can depend on references to enums being stable you can just writeg == Gender.FEMALE
. 4. (Personal opinion) such code is much harder to read and will produce slightly more confusing errors.Maja Piechotka– Maja Piechotka2013年01月05日 10:54:56 +00:00Commented Jan 5, 2013 at 10:54 -
@MaciejPiechotka good catch about g. Yes, microoptimization is a nonbenefit, but neither is it a drawback. 100% code coverage is a benefit iff that is one of your goals and your code coverage tool does not check asserts (which it should not).emory– emory2013年01月05日 13:37:48 +00:00Commented Jan 5, 2013 at 13:37
-
Then why would it be one of my goals? The 'interesting' part should be tested for all edge cases (regardless if they map to lines of code) and 'boring' parts can be simply skipped to save time on testing. IMHO code coverage is bad metric of tests.Maja Piechotka– Maja Piechotka2013年01月05日 15:29:05 +00:00Commented Jan 5, 2013 at 15:29
-
I appreciate that this post was seven years ago, but assuming not(Male) implies Female is rather a dangerous one, in these more enlightened days! In many ways, this example highlights why you SHOULD have a default :-)Andrew– Andrew2020年06月03日 05:09:39 +00:00Commented Jun 3, 2020 at 5:09
Explore related questions
See similar questions with these tags.