| Consider a switch statement that doesn't handle all possible values and doesn't |
| have a default: |
| |
| ```java |
| enum Colors { RED, GREEN, BLUE } |
| |
| switch (color) { |
| case RED: |
| case GREEN: |
| paint(color); |
| break; |
| } |
| ``` |
| |
| The author's intent isn't clear. There are three possibilities: |
| |
| 1. The default case is known to be impossible. This could be made clear by |
| adding: \ |
| `default: throw new AssertionError(color);` |
| |
| 2. The code intentionally 'falls out' of the switch on the default case, and |
| execution continues below. This could be made clear by adding: \ |
| `default: // fall out` |
| |
| 3. The code has a bug, and the missing cases should have been handled. |
| |
| To avoid this ambiguity, the Google Java Style Guide [requires][style] each |
| switch statement on an enum type to either handle all values of the enum, or |
| have a default statement group. |
| |
| [style]: https://google.github.io/styleguide/javaguide.html#s4.8.4.3-switch-default |
| |
| ## Library skew |
| |
| If libraries are compiled against different versions of the same enum it's |
| possible for the switch statement to encounter an enum value despite it |
| otherwise being thought to be exhaustive. If there is no default branch code |
| execution will simply fall out of the switch statement. |
| |
| Since developers may have assumed this to be impossible, it may be helpful to |
| add a default branch when library skew is a concern, however, you may not want |
| to give up checking to ensure that all cases are handled. Therefore if a default |
| branch exists with a comment containing "skew", the default will not be |
| considered for exhaustiveness. For example: |
| |
| ```java |
| enum TrafficLightColour { RED, GREEN, YELLOW } |
| |
| void approachIntersection(TrafficLightColour state) { |
| switch (state) { |
| case GREEN: |
| proceed(); |
| break; |
| case YELLOW: |
| case RED: |
| stop(); |
| break; |
| default: // In case of skew we may get an unknown value, always stop. |
| stop(); |
| break; |
| } |
| } |
| ``` |
| |
| In this case the default branch is providing runtime safety for unknown enum |
| values while also still enforcing that all known enum values are handled. |
| |
| Note: The [UnnecessaryDefaultInEnumSwitch](UnnecessaryDefaultInEnumSwitch.md) |
| check will not classify the default as unnecessary if it has the "skew" comment. |