File: StatementSwitchToExpressionSwitch.md

package info (click to toggle)
error-prone-java 2.18.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 23,204 kB
  • sloc: java: 222,992; xml: 1,319; sh: 25; makefile: 7
file content (91 lines) | stat: -rw-r--r-- 2,508 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
We're trying to make `switch` statements simpler to understand at a glance.
Misunderstanding the control flow of a `switch` block is a common source of
bugs.

### Statement `switch` statements:

*   Have a colon between the `case` and the case's code. For example, `case
    HEARTS:`
*   Because of the potential for fall-through, it takes time and cognitive load
    to understand the control flow for each `case`
*   When a `switch` block is large, just skimming each `case` can be toilsome
*   Fall-though can also be conditional (see example below). In this scenario,
    one would need to reason about all possible flows for each `case`. When
    conditionally falling-through multiple `case`s in a row is possible, the
    number of potential control flows can grow rapidly

### Expression `switch` statements

*   Have an arrow between the `case` and the case's code. For example, `case
    HEARTS ->`
*   With an expression `switch` statement, you know at a glance that no cases
    fall through. No control flow analysis needed
*   Safely and easily reorder `case`s (within a `switch`)
*   It's also possible to group identical cases together (`case A, B, C`) for
    improved readability

### Examples

``` {.bad}
enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}

private void foo(Suit suit) {
  switch(suit) {
    case HEARTS:
System.out.println("Red hearts");
    case DIAMONDS:
System.out.println("Red diamonds");
    case SPADES:
      // Fall through
    case DIAMONDS:
      bar();
      System.out.println("Black suit");
    }
}
```

Which can be simplified into the following expression `switch`:

``` {.good}
enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}

private void foo(Suit suit) {
  switch(suit) {
    case HEARTS -> System.out.println("Red hearts");
    case DIAMONDS -> System.out.println("Red diamonds");
    case CLUBS, SPADES -> {
      bar();
      System.out.println("Black suit");
    }
  }
}
```

Here's an example of a complex statement `switch` with conditional fall-through
and complex control flows. How many potential execution paths can you spot?

``` {.bad}
enum Suit {HEARTS, CLUBS, SPADES, DIAMONDS}

private int foo(Suit suit){
  switch(suit) {
    case HEARTS:
      if (bar()) {
        break;
      }
      // Fall through
    case CLUBS:
      if (baz()) {
        return 1;
      } else if (baz2()) {
        throw new AssertionError(...);
      }
      // Fall through
    case SPADES:
      // Fall through
    case DIAMONDS:
      return 0;
  }
  return -1;
}
```