44

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?

3
  • 9
    Its up to your... I mean supervisor's code style.
    – S.D.
    Jan 4, 2013 at 16:01
  • 1
    I 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
    Jan 5, 2013 at 3:29
  • 6
    Me 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
    Jan 8, 2013 at 20:32

8 Answers 8

33

It seems there are three cases when a default statement is not necessary:

  1. 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 a default case if anything changes _ you could log or warn the user about a wrong value.

  2. 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.

  3. 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.

4
  • 16
    In 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
    Jan 4, 2013 at 7:33
  • 11
    A 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
    Jan 4, 2013 at 10:34
  • Does this mean you should always have an else clause after every if/else if even if you know that shouldn't happen? Doesn't seem like a good idea to me...
    – jadkik94
    Jan 9, 2013 at 22:31
  • 2
    If 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
    Jan 14, 2013 at 15:03
29

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.

4
  • 1
    what is an assert ?
    – FLY
    Jan 4, 2013 at 15:01
  • 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
    Jan 4, 2013 at 16:14
  • I've edited my previous comment with a link to the wikipedia
    – FLY
    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
    Jan 7, 2013 at 21:41
12

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.

7
  • 2
    +1 for catching the problem at compile-time and not at run-time.
    – SylvainD
    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
    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
    Jan 5, 2013 at 3:32
  • 1
    Obviously, 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
    Jan 5, 2013 at 12:11
10

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:

  1. 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!
  2. 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

3
  • Not only at the end of a ladder. The question is: do I need an else after an if. But as you said, no, it's not.
    – ott--
    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
    Jan 5, 2013 at 3:16
  • Good point, @emory - that wasn't very clear, was it... edited :)
    – Andrew
    Jan 5, 2013 at 7:13
6

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.

2

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.

0

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.

-2

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?

9
  • 1
    1. 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'). Jan 5, 2013 at 10:52
  • 1
    3. When does Gender . FEMALE . equals ( FEMALE ) ; evaluate to false? You meant Gender.FEMALE.equals (g) but since you can depend on references to enums being stable you can just write g == Gender.FEMALE. 4. (Personal opinion) such code is much harder to read and will produce slightly more confusing errors. 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
    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. 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
    Jun 3, 2020 at 5:09

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