Operators ·
‹ Previous Next ›
⏱ 5 min read Modified: 2026-07-12

Switch-Case Statement in Java

In this lesson, we will talk about the switch statement in Java. The switch statement in Java is a conditional construct that lets you compare a variable against a list of values.

Java 14 introduced significant changes to its syntax. We will look at how a switch block was written before Java 14 and what changed in the fourteenth version.

1. Classic switch (Before Java 14)

Let's look at switch with an example: a number from 1 to 3 is given. If it is 1, the green traffic light turns on; 2 — yellow; 3 — red. For any other number, the default block is executed:

public class TrafficLight {
    public static void main(String[] args) {
        int x = 3;
        switch (x) {
            case 1:
                System.out.println("Green");
                break;
            case 2:
                System.out.println("Yellow");
                break;
            case 3:
                System.out.println("Red");
                break;
            default:
                System.out.println("Invalid value");
                break;
        }
    }
}

The general form of the switch statement:

switch (expression) {
    case value1:
        // Code block 1
        break;
    case value2:
        // Code block 2
        break;
    ...
    case valueN:
        // Code block N
        break;
    default:
        // Default block
}

In the parentheses, we specify an expression whose value is compared against the list of values that follow the case keyword. If the expression matches value1, the code block after value1 is executed.

The expression in a switch must be of type char, byte, short, int, enum (since Java 6), or String (since Java 7). Using any other type, such as float, long, or boolean, results in a compilation error.

The switch statement can only check for equality. Operators such as >= and <= are not allowed.

For multiple case values, you can specify a single block, as shown in the following example:

public class SwitchExample1 {
    public static void main(String[] args) {
        int month = 4;
        String season;
        switch (month) {
            case 12:
            case 1:
            case 2:
                season = "Winter";
                break;
            case 3:
            case 4:
            case 5:
                season = "Spring";
                break;
            case 6:
            case 7:
            case 8:
                season = "Summer";
                break;
            case 9:
            case 10:
            case 11:
                season = "Autumn";
                break;
            default:
                season = "Not a Month";
        }
        System.out.println("April is in the " + season + ".");
    }
}

If the expression in a switch has a type smaller than int (byte, short, or char), each case constant must fit that type. For example, the following code will not compile because the value 129 is out of range for byte:

byte number = 2;
switch (number) {
    case 13:
    case 129: //compiler error
}

It is also not allowed to use multiple case constants with the same value. The following code block will not compile:

int number = 90;
switch (number) {
    case 50:
        System.out.println("50");
    case 50:
        System.out.println("50"); //compile error
    case 140:
        System.out.println("140");
    default:
        System.out.println("default");
}

A switch expression can also contain values of the wrapper types Character, Byte, Short, and Integer:

switch (Integer.valueOf(9)) {
    case 9:
        System.out.println("9");
}

Case constants are evaluated from top to bottom, and the first matching case constant in the switch serves as the entry point. The corresponding block and all subsequent blocks are executed — this is called fall-through. For example:

public class SwitchExample2 {
    public static void main(String[] args) {
        String str = "potato";
        switch (str) {
            case "tomato":
                System.out.print("tomato ");
            case "potato":
                System.out.print("potato ");
            case "cucumber":
                System.out.print("cucumber ");
            default:
                System.out.println("any");
        }
    }
}

The output:

potato cucumber any

To exit a switch, use the break keyword. For example, let's modify the previous example so that only one word is printed:

String str = "potato";
switch (str) {
    case "tomato":
        System.out.print("tomato ");
        break;
    case "potato":
        System.out.print("potato ");
        break;
    case "cucumber":
        System.out.print("cucumber ");
        break;
    default:
        System.out.println("any");
}

The result:

potato 

The default section in a switch handles all values that are not explicitly listed in one of the case sections. The default section can be placed anywhere, not necessarily at the end. If no case constant matches, default becomes the entry point, and fall-through continues into the sections that follow it:

public class SwitchExample3 {
    public static void main(String[] args) {
        int z = 8;
        switch (z) {
            case 1:
                System.out.println("Fall to one");
            default:
                System.out.println("default");
            case 3:
                System.out.println("Fall to three");
            case 4:
                System.out.println("Fall to four");
        }
    }
}

Since Java 7, you can use String objects in a switch. For example:

String exam = "OCPJP 8";
switch (exam) {
    case "OCPJP 7":
        System.out.print(exam + ": 1Z0-804");
        break;
    case "OCPJP 8":
        System.out.print(exam + ": 1Z0-809");
        break;
    default:
        System.out.print(exam + ": ----");
        break;
}

Important

If the variable in a switch is null (for example, String exam = null;), a NullPointerException is thrown at runtime. There is no compilation error, which is why this case trips up so many candidates in interviews. Always check a string for null before the switch.

The following example shows a classic switch with an enum. Note that in the case labels the constant name is written without the enum name — BIG, not CoffeeSize.BIG:

enum CoffeeSize { BIG, HUGE, OVERWHELMING }

public class CoffeeMachine {
    public static void main(String[] args) {
        CoffeeSize coffeeSize = CoffeeSize.BIG;
        switch (coffeeSize) {
            case BIG:
                System.out.println("Price: 2");
                break;
            case HUGE:
                System.out.println("Price: 3");
                break;
            case OVERWHELMING:
                System.out.println("Price: 4");
                break;
        }
    }
}

2. Switch Expressions in Java 14

Now let's move on to the changes introduced in Java 14. Previously, switch was only a statement; now there is also a switch expression. Switch expressions first appeared not in Java 14 but in Java 12 as a preview feature. They were refined in Java 13, and in Java 14 they became a standard part of the language.

Switch expressions significantly simplify the code and make it more readable thanks to the arrow syntax (arrow case).

Let's look at a switch example in Java 14:

public static void main(String[] args) {
   int x = 2;
   switch (x) {
       case 1 -> System.out.println("Green");
       case 2 -> System.out.println("Yellow");
       case 3 -> {
           System.out.println("Red");
           System.out.println("You cannot move");
       }
       default -> System.out.println("Invalid number");
   }
}

The output:

Yellow

Notice what has changed compared to the previous version. Instead of a colon, an arrow is used — the arrow case. After the arrow, there can be either a single line of code or a block of code. If it is a block, curly braces are used.

Another change in the fourteenth version of Java: with the arrow syntax, only one block is ever executed. Fall-through into the next code block, as in the old version of switch, does not happen. As a result, there is no need to write a break for each code block, as was required before.

Very often a switch must not only execute a block of code but also return a value:

public class SwitchExample2 {
   public static void main(String[] args) {
       int month = 4;
       String season = switch (month) {
           case 12, 1, 2 -> "Winter";
           case 3, 4, 5 -> "Spring";
           case 6, 7, 8 -> "Summer";
           case 9, 10, 11 -> "Autumn";
           default -> "Not a Month";
       };
       System.out.println("April is in the " + season + ".");
   }
}

Note one more improvement: several values in a single case label can now be listed separated by commas — case 12, 1, 2.

Java 14 also added the reserved word yield, which returns a value from a switch expression written with the old colon syntax:

public class SwitchExample1 {
   public static void main(String[] args) {
       int month = 4;
       String season = switch (month) {
           case 12, 1, 2:
               yield "Winter";
           case 3, 4, 5:
               yield "Spring";
           case 6, 7, 8:
               yield "Summer";
           case 9, 10, 11:
               yield "Autumn";
           default:
               yield "Not a Month";
       };
       System.out.println("April is in the " + season + ".");
   }
}

The word yield is also used when you need to return a value from a curly-brace block in the arrow syntax:

CoffeeSize coffeeSize = CoffeeSize.BIG;
double price = switch (coffeeSize) {
    case BIG -> 2;
    case HUGE -> 3;
    case OVERWHELMING -> {
        System.out.println("The largest size!");
        yield 4;
    }
};

A switch expression must return a value for every possible input. If the type of the expression is an enum and all of its constants are covered by case labels, the default block can be omitted, as in the example above. For types such as int or String, the default block is required; otherwise, the code will not compile.

What is the difference between a reserved word and a keyword? Keywords can never be used as identifiers. Reserved words, however, can be used as identifiers outside of their context. Outside the switch block, you can create a variable named yield, and there will be no compilation error:

public static void main(String[] args) {
    int month = 4;
    String season = switch (month) {
        case 12, 1, 2:
            yield "Winter";
        default:
            yield "Not a Month";
    };
    int yield = 6;
}

But you cannot create a variable named after a keyword, such as case, even outside the switch block — it results in a compilation error.

Good to know

The evolution of switch did not stop at Java 14. In Java 21, switch gained pattern matching: case labels can specify types (case Integer i ->) and a dedicated case null label, which lets you handle null without a NullPointerException.

Here is a pattern matching example (Java 21):

public class PatternMatchingExample {
    public static void main(String[] args) {
        Object obj = 42;
        String result = switch (obj) {
            case null -> "It's null";
            case Integer i when i > 0 -> "Positive number: " + i;
            case Integer i -> "Integer: " + i;
            case String s -> "String of length " + s.length();
            default -> "Some other type: " + obj.getClass().getSimpleName();
        };
        System.out.println(result);
    }
}

Program output:

Positive number: 42

Note the case Integer i when i > 0 label — this is a guarded pattern (a case label with a condition, using the when keyword): it only matches when the object is an Integer and also satisfies the when condition. If the condition is false, matching continues to the next label — here, the more general case Integer i.

3. Classic switch vs Switch Expressions

Feature Classic switch Switch expression (Java 14)
Label syntax case 1: case 1 -> (or case 1: with yield)
Multiple values per label case 1: case 2: (separate labels) case 1, 2 (comma-separated)
Fall-through Yes, unless break is used No with the arrow syntax
Returns a value No, executes code only Yes, via the arrow or yield
default block Optional Required, except for an enum with all constants covered

Frequently Asked Questions

What happens if a null string is passed to a switch?

A NullPointerException is thrown at runtime — both in a classic switch and in a switch expression. The compiler does not catch this. Check the variable for null before the switch, or, starting with Java 21, use a dedicated case null label.

Which types cannot be used in a switch expression?

You cannot use long, float, double, or boolean. The allowed types are char, byte, short, int, their wrapper classes, enum (since Java 6), and String (since Java 7). Starting with Java 21, thanks to pattern matching, any reference type can be used in a switch.

How is yield different from break in a switch?

break simply terminates the switch statement and returns nothing. yield terminates the switch expression and returns a result from it. Also, yield is a reserved word rather than a keyword: you can create a variable named yield, but not one named break.

Is the default block required in a switch expression?

A switch expression must cover all possible values. If the expression type is an enum and all of its constants are listed in case labels, the default block can be omitted. For int, String, and other types, default is required, otherwise the code will not compile. In a classic switch statement, default is always optional.

Comments

Please log in or register to have a possibility to add comment.