Concepts / Traditional Switch Syntax in Java

Traditional Switch Syntax in Java

A switch statement tests one expression and jumps to the case label that matches its value.

  • Programming

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.

switch (count)count is 2case 1skippedcase 2jump lands herecase 3skippeddefaultnot reached1 does not match2 matches3 does not matchonly if nothing matched
Given the value of count, which case label does control jump to, and which labels are skipped?

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.

java
Notes on the code
  • 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.

FeatureTraditional syntaxJava 17 arrow syntax
Case label endingA colon after the constant listAn arrow followed by one statement
Ending a case bodyA break statement is needed to stop before the next caseThe arrow form does not fall through to the next case
Fall-through behaviorHappens when a case body has no breakNot the default behavior
Recommended for new codeNo, it is still common in existing codeYes, 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.

java
Notes on the code
  • 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
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.

case 2 bodyprints twocase 3 bodyprints threebreakswitch ends heredefault bodyskippedno break, falls throughreaches breaknot reached
When the case 2 body has no break, which bodies run, and at which statement does execution stop?
Worked example

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.

  1. 1
    Find the selector value

    The switch tests count, and count is 2.

  2. 2
    Find the matching label

    The label case 2 matches, so control jumps to the position just after that label.

  3. 3
    Check for a break

    The case 2 body has no break, so the next body is also executed. This is where the unexpected output begins.

  4. 4
    Find where execution stops

    The case 3 body reaches a break, so the switch ends and default is not run.

Result

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 like
    double price = 2.5; switch (price) { ... }
    Why it fails

    The source says the expression may be int, short, byte, char, String, or an enum type, but never double or float.

    Do this instead

    Convert 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 like

    In the traditional form, a case 2 body with no break continues into case 3.

    Why it fails

    In the traditional form, control keeps running into the next body until a break or the end of the switch.

    Do this instead

    Check each case body for a break before deciding which lines will run.

  • Common mistake

    Reusing a constant in two case labels

    Why it fails

    The source states that all case constants must be different.

    Do this instead

    Give 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 fails

    The source says a switch can have only one default entry.

    Do this instead

    Merge the fallback behavior into a single default position.

  • Common mistake

    Mixing literal types in a constant list

    Why it fails

    The source says the literals in a constant list must be of the same type as the expression.

    Do this instead

    Use only integer literals for an int switch, character literals for a char switch, and string literals for a String switch.

Practice Tracing a Switch

MEDIUM

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

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.