🚀 Modern Java 17 → 25 · Advanced

Text blocks & switch expressions recap in Java

Modern replacements for older idioms.

🧩 The mysteryEscaped quotes, \n everywhere, a + at the end of every line: that's JSON inside an old Java string. Text blocks and switch expressions delete whole categories of boilerplate and bugs.

Text blocks

A text block (final in Java 15) starts with """ and a line break; the content begins on the next line. No \n escapes, no escaped quotes, no + chains.

String json = """
    {
      "name": "Ada",
      "lang": "Java"
    }
    """;

Incidental indentation

The compiler strips the common indentation, measured from the least-indented line, and the closing """ counts as a line. Lines indented more than that minimum keep their extra spaces. Move the closing delimiter left and more indentation survives.

🔮 Predict it

Your turn

The closing delimiter is indented 4 spaces; the text lines 6 and 8. What prints?

String s = """
      Hi
        there
    """;
System.out.print(s);
  1. Hi there
  2. Hi there
  3. Hi there
Show the answer

The closing """ is the least-indented line (4 spaces), so exactly 4 spaces are stripped from every line. "Hi" keeps 2 and "there" keeps 4.

Switch expressions

A switch expression (final in Java 14) produces a value. Arrow cases never fall through, labels can be grouped (case 6, 7 ->), and inside a { } block, **yield** supplies the value.

String type = switch (day) {
    case 1, 2, 3, 4, 5 -> "weekday";
    case 6, 7 -> {
        String t = "weekend";
        yield t.toUpperCase();
    }
    default -> "invalid";
};
🔮 Predict it

No fall-through

What does this print?

int code = 2;
String s = switch (code) {
    case 1 -> "one";
    case 2 -> {
        String t = "tw";
        yield t + "o";
    }
    default -> "many";
};
System.out.println(s);
  1. two
  2. many
  3. twomany
Show the answer

two. Case 2's block yields "tw" + "o". Arrow cases run only their own right-hand side, so execution never falls into default. Fall-through exists only in the old colon form (case 2: with no break).

⚠️ The trap

Exhaustive or it won't compile

A switch expression must produce a value for every possible input. An int has far more values than 1 and 2, so without default this doesn't compile. (Over a sealed type or an enum, covering every case is enough.)

int n = 3;
String s = switch (n) {
    case 1 -> "one";
    case 2 -> "two";
};  // compile error: not exhaustive
💼 In the real world

Spot the old idioms

Modernizing code? "line1\n" + "line2\n" becomes a text block. case 1: x = "a"; break; becomes an arrow case in a switch expression. if (o instanceof Foo) { Foo f = (Foo) o; } becomes pattern matching. A class with fields, equals, hashCode and toString becomes a record.

Key takeaways

  1. Text block content starts on the line after the opening """
  2. The closing """ position controls how much indent is stripped
  3. Arrow cases never fall through; group labels: case 6, 7 ->
  4. yield returns a value from a { } block in a switch expression
🤯 Did you know?

Text blocks were plan B: Java 12 was to get backtick "raw string literals", but that JEP was withdrawn before release and redesigned as text blocks.

Practice questions

What does this print?

String s = """
    Hi
      there
    """;
System.out.print(s);
  1. Hi there
  2. Hi there
  3. Hi there
  4. Hi there
Check your answer

Hi there. The closing delimiter is indented 4 spaces, the minimum, so 4 spaces are stripped from every line. "there" keeps its extra 2 spaces.

What does this print?

int day = 6;
String type = switch (day) {
    case 1, 2, 3, 4, 5 -> "weekday";
    case 6, 7 -> {
        String t = "weekend";
        yield t.toUpperCase();
    }
    default -> "invalid";
};
System.out.println(type);
  1. WEEKEND
  2. weekend
  3. weekday
  4. invalid
Check your answer

WEEKEND. 6 matches case 6, 7. Inside a block, yield supplies the switch's value.

Next: how do brand-new features reach you? Preview flags, incubator modules, and how a feature graduates.