Java 12 & 13: Switch Expressions and Text Blocks Begin
Java 12 and 13 were transitional releases that introduced two features in preview that would become cornerstones of modern Java — switch expressions and text blocks (multiline strings). Java 12 also added the Teeing collector and Compact Number Formatting.
Java Evolution — Part 5
Java 12 (March 19, 2019) and Java 13 (September 17, 2019) were non-LTS releases that served as incubators for features that would be finalised in Java 14 and 15. The most significant previews — switch expressions and text blocks — fundamentally changed how Java developers write everyday code.
Switch Expressions (Preview — Java 12 & 13)
The traditional switch statement in Java had two well-known problems. First, it was a statement, not an expression — it could not return a value, so you needed a mutable variable to capture the result. Second, it had fall-through semantics by default, meaning a missing break would silently execute the next case.
Java 12 (JEP 325) introduced switch expressions as a preview feature, and Java 13 (JEP 354) refined them with the yield keyword.
The Old Switch Statement
// Before Java 12 — verbose, fall-through proneString dayType;switch (day) { case MONDAY: case TUESDAY: case WEDNESDAY: case THURSDAY: case FRIDAY: dayType = "Weekday"; break; case SATURDAY: case SUNDAY: dayType = "Weekend"; break; default: throw new IllegalArgumentException("Unknown day: " + day);}The New Switch Expression (Arrow Form)
// Java 12+ — switch as an expression with arrow labelsString dayType = switch (day) { case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Weekday"; case SATURDAY, SUNDAY -> "Weekend";};The arrow (->) form has no fall-through. Each case is independent. Multiple labels can be grouped with commas. The entire switch is an expression that produces a value.
The yield Keyword (Java 13)
When a case arm needs to execute multiple statements before producing a value, you use a block with yield:
int numLetters = switch (day) { case MONDAY, FRIDAY, SUNDAY -> 6; case TUESDAY -> 7; case THURSDAY, SATURDAY -> 8; case WEDNESDAY -> { System.out.println("Computing letters for Wednesday..."); yield 9; // yield produces the value from a block }};
yieldis a context-sensitive keyword — it is only special inside a switch block. You can still useyieldas a variable or method name elsewhere.
Exhaustiveness
Switch expressions must be exhaustive — every possible value of the selector must be handled. For enums, the compiler verifies this at compile time. For other types, a default case is required.
// Compiler error if any Day enum constant is missing and no defaultString result = switch (day) { case MONDAY -> "Start of the week"; case FRIDAY -> "End of the week"; // Missing cases — compiler error!};Text Blocks (Preview — Java 13)
JEP 355 introduced text blocks as a preview feature in Java 13. A text block is a multi-line string literal delimited by triple quotes ("""). It eliminates the need for explicit \n characters and string concatenation when embedding multi-line content like JSON, HTML, SQL, or XML.
The Problem with Traditional String Literals
// Before Java 13 — painful multi-line stringsString html = "<html>\n" + " <body>\n" + " <p>Hello, world</p>\n" + " </body>\n" + "</html>\n";
String json = "{\n" + " \"name\": \"Alice\",\n" + " \"age\": 30\n" + "}";
String sql = "SELECT u.name, u.email\n" + "FROM users u\n" + "WHERE u.active = true\n" + "ORDER BY u.name";Text Blocks in Java 13
// Java 13 — text blocksString html = """ <html> <body> <p>Hello, world</p> </body> </html> """;
String json = """ { "name": "Alice", "age": 30 } """;
String sql = """ SELECT u.name, u.email FROM users u WHERE u.active = true ORDER BY u.name """;Indentation Handling
The Java compiler automatically strips incidental whitespace — the common leading whitespace shared by all lines. The position of the closing """ determines the indentation baseline.
// The closing """ on its own line sets the baseline to column 0String a = """ hello world """;// a = "hello\nworld\n"
// The closing """ indented sets the baseline to that indentationString b = """ hello world """;// b = " hello\n world\n"Escape Sequences in Text Blocks
Text blocks support two new escape sequences (finalised in Java 15):
// \s — explicit trailing space (prevents stripping)String padded = """ red \s green\s blue \s """;
// \ at end of line — line continuation (no newline in output)String single = """ This is a very long string that \ continues on the next line. """;// single = "This is a very long string that continues on the next line.\n"Teeing Collector (Java 12)
Collectors.teeing() (JEP 12) allows a stream to be processed by two independent collectors simultaneously, with the results merged by a function. This avoids iterating the stream twice.
// Calculate min and max in a single passrecord MinMax(int min, int max) {}
MinMax result = Stream.of(3, 1, 4, 1, 5, 9, 2, 6) .collect(Collectors.teeing( Collectors.minBy(Integer::compareTo), Collectors.maxBy(Integer::compareTo), (min, max) -> new MinMax( min.orElseThrow(), max.orElseThrow() ) ));
System.out.println(result); // MinMax[min=1, max=9]Another practical example — compute both the sum and count in one pass to calculate an average:
double average = Stream.of(10, 20, 30, 40, 50) .collect(Collectors.teeing( Collectors.summingInt(Integer::intValue), Collectors.counting(), (sum, count) -> (double) sum / count ));// 30.0Compact Number Formatting (Java 12)
NumberFormat.getCompactNumberInstance() formats numbers in a human-readable compact form:
NumberFormat shortFmt = NumberFormat.getCompactNumberInstance( Locale.US, NumberFormat.Style.SHORT);
System.out.println(shortFmt.format(1_000)); // 1KSystem.out.println(shortFmt.format(1_500_000)); // 2MSystem.out.println(shortFmt.format(1_200_000_000));// 1B
NumberFormat longFmt = NumberFormat.getCompactNumberInstance( Locale.US, NumberFormat.Style.LONG);System.out.println(longFmt.format(1_500_000)); // 2 millionString Methods (Java 12)
Java 12 added String.indent(n) and String.transform(f):
// indent — add or remove leading whitespace from each lineString indented = "hello\nworld".indent(4);// " hello\n world\n"
// transform — apply a function to the string (useful in method chains)String result = " hello " .transform(String::strip) .transform(String::toUpperCase);// "HELLO"Summary
Java 12 and 13 were stepping stones. The features they introduced in preview — switch expressions and text blocks — would become two of the most-used features in modern Java.
| Feature | Version | Key Benefit |
|---|---|---|
| Switch Expressions (Preview) | 12 & 13 | Expressions, no fall-through, arrow syntax |
yield keyword | 13 | Multi-statement switch expression arms |
| Text Blocks (Preview) | 13 | Multi-line strings without escape noise |
| Teeing Collector | 12 | Two collectors in one stream pass |
| Compact Number Formatting | 12 | Human-readable number display |
String.indent() / transform() | 12 | Indentation control and functional string chains |