Traditional Switch Syntax in Java
A switch statement tests one expression and jumps to the case label that matches its value.
When a Switch Gives an Unexpected Result
A switch statement is one of the most compact ways Java has to choose among several possible paths. Instead of writing a long chain of separate comparisons, you list the possible positions in one place and let the value of one expression decide which position runs. That compactness is useful, but it also means that a switch can hide where control actually goes. Many programmers have stared at a switch that printed more lines than they expected, or none at all, and could not say why.
The source for this article makes an important observation: most of the difficulty with switch statements is not in running them but in reading them. When a switch produces a result you did not expect, the useful question is which position control jumped to, and why that position was chosen. This article gives you the vocabulary and the rules needed to answer that question for yourself, starting with the traditional syntax you will still meet in existing code.
How a Value Selects a Jump Point
A switch statement tests the value of one expression. Depending on that value, control jumps directly to a particular position inside the switch statement, and the code at that position runs. Each position is marked by a case label, and at most one position can be marked as the default. Think of the switch body as a set of named landing spots. The selector value determines which spot you land on, and the code from that spot onward is what executes.
The diagram shows the key idea. The switch does not test each case in turn and run the first one that is true the way an if chain does. Instead, the selector value is matched against the constants in the case labels, and control moves to the one whose constant matches. The default position is used when no constant matches. Once control lands on a position, what happens next depends on what the code at that position says, which is why the next sections matter so much.
Which Expression Types a Switch Can Test
A switch statement only accepts expressions of certain types. Before you can read a case label, you need to know whether the switch is even legal for the value you are testing. According to the source, the expression may be one of the following.
- The primitive integer types int, short, and byte
- The primitive type char
- The type String
- An enum type, whose values are named constants
The source introduces enum types only briefly and points forward to a later subsection for full treatment. For now, treat an enum as a type whose values are named constants. The source material for this article does not go further into wrapper types or other related types, so this article does not make claims about them.
Reading a Case Label
The positions a switch can jump to are marked with case labels. A case label takes the form case followed by a constant list. The constant list consists of one or more literals of the same type as the expression in the switch, separated by commas. So a label can hold a single value, or several values that should all lead to the same position. The literals must match the type of the expression: an int switch takes integer literals, a char switch takes character literals, and a String switch takes string literals.
- case 1, 7 is a constant list of two int literals separated by a comma
- The arrow is a hyphen followed by a greater-than character, followed by one statement
- default is the single position used when no other label matches
Notice that this example uses the newer arrow form, which the source treats first. Reading the label is the same skill in both syntaxes. The label tells you which constant values lead to that position, and the constant list tells you exactly which literals can appear there. Two rules are worth remembering from the source: a switch can have only one default entry, and all case constants must be different from one another.
Traditional Syntax Compared with Java 17
Java has two different syntaxes for switch statements. The original syntax was modeled on the C programming language, and the source describes it as error-prone and somewhat awkward to read. It is still common because a great deal of existing code uses it, so you need to be able to read it. The newer syntax requires Java 17 and is an improvement over the original. The source's advice is to use the new syntax when you write new code. Both forms rest on the same idea: a value selects a jump point.
| Feature | Traditional syntax | Java 17 arrow syntax |
|---|---|---|
| Case label ending | A colon after the constant list | An arrow followed by one statement |
| Ending a case body | A break statement is needed to stop before the next case | The arrow form does not fall through to the next case |
| Fall-through behavior | Happens when a case body has no break | Not the default behavior |
| Recommended for new code | No, it is still common in existing code | Yes, according to the source |
Traditional and arrow-style switch syntax compared. The arrow-form details are taken from the source's description of the newer syntax.
Tracing Fall-Through Step by Step
In the traditional form, a case body that has no break does not stop at the end of its own lines. Control continues into the next case body, and the next, until a break is reached or the switch ends. This is called fall-through. The following example is an original sketch written for this article. Read it before you run it, and work out which lines execute for a given value of count.
- count is 2, so control jumps to the case 2 label
- The case 2 body has no break, so execution continues into case 3
- The break after the case 3 body stops the switch
- The default body is skipped
What do you think happens?
Before you look, decide: when count is 2, which lines print, and on which line does execution stop?
Reveal answer
It prints two, then three. Execution stops at the break after the case 3 body.
Control jumps to the case 2 label. That body has no break, so it falls through into the case 3 body. The break there ends the switch, so the default body never runs.
Locating where the unexpected output begins
A switch prints three lines when you expected only one. The value of count is 2. Find the point where control first went somewhere you did not expect.
- 1Find the selector value
The switch tests count, and count is 2.
- 2Find the matching label
The label case 2 matches, so control jumps to the position just after that label.
- 3Check for a break
The case 2 body has no break, so the next body is also executed. This is where the unexpected output begins.
- 4Find where execution stops
The case 3 body reaches a break, so the switch ends and default is not run.
The unexpected output starts at the missing break in the case 2 body. The extra line comes from falling through into case 3.
Mistakes That Hide Where Control Lands
Common mistake Switching on a double or float value
What it looks likedouble price = 2.5; switch (price) { ... }Why it failsThe source says the expression may be int, short, byte, char, String, or an enum type, but never double or float.
Do this insteadConvert the value to a permitted type where that makes sense, or use if and else comparisons instead.
Common mistake Assuming a case body stops by itself
What it looks likeIn the traditional form, a case 2 body with no break continues into case 3.
Why it failsIn the traditional form, control keeps running into the next body until a break or the end of the switch.
Do this insteadCheck each case body for a break before deciding which lines will run.
Common mistake Reusing a constant in two case labels
Why it failsThe source states that all case constants must be different.
Do this insteadGive each constant only one label, and use the constant list form to group values that share a body.
Common mistake Using two default entries
Why it failsThe source says a switch can have only one default entry.
Do this insteadMerge the fallback behavior into a single default position.
Common mistake Mixing literal types in a constant list
Why it failsThe source says the literals in a constant list must be of the same type as the expression.
Do this insteadUse only integer literals for an int switch, character literals for a char switch, and string literals for a String switch.
Practice Tracing a Switch
Using the traditional switch from the fall-through example, trace what prints when count is 1, and then what prints when count is 4. For each value, name the case label control jumps to and state where execution stops.
Hints
- For count equal to 1, find the case 1 label first, then follow the bodies downward until you reach a break.
- For count equal to 4, check whether any case label matches. If none does, control goes to default.
Write a traditional switch on a char variable grade that prints a message for the letters A and B together, then adds a break so that C does not fall into them. Explain in one sentence why the break matters.
Hints
- Use two case labels that share one body, such as case 'A': followed by case 'B': with the body after them.
- The break belongs after the body that should end the switch.
Key Takeaways
- A switch statement tests one expression and jumps to the case label whose constant matches its value, or to default when none does.
- The expression may be int, short, byte, char, String, or an enum type, but never double or float.
- A case label is case followed by one or more same-type literals separated by commas; only one default is allowed and all case constants must differ.
- The traditional syntax is still common and can fall through from one case body into the next when there is no break, so the place where execution stops is the key question when tracing an unexpected result.
- The source recommends the Java 17 syntax for new code, but reading the traditional form remains an essential skill.