Skip to content

Java 12

Neelu edited this page Jul 26, 2026 · 1 revision

☕ Java 12: Switch Expressions Arrive (Preview)

Release Date: March 19, 2019 | Type: Standard (non-LTS) | Status: ⚠️ End of Life


📋 Table of Contents

  1. Overview
  2. Core Features
  3. Best Practices

🎯 Overview

Java 12 previews the feature that quietly reshapes how modern Java code reads: switch expressions. It also adds a genuinely useful Collectors.teeing() and compact number formatting.

flowchart LR
    A["Old switch statement\nfall-through, mutable variable"] -->|JEP 325 Preview| B["switch expression\narrow syntax, yields a value"]
    B --> C["Standardized in Java 14"]
Loading

🚀 Core Features

1️⃣ Switch Expressions (Preview) — --enable-preview

What: switch can now be an expression that returns a value, using arrow (->) syntax with no fall-through.

// Old switch statement — verbose, error-prone fall-through
String result;
switch (day) {
    case MONDAY:
    case TUESDAY:
    case WEDNESDAY:
    case THURSDAY:
    case FRIDAY:
        result = "Weekday";
        break;
    case SATURDAY:
    case SUNDAY:
        result = "Weekend";
        break;
    default:
        throw new IllegalStateException();
}

// New switch expression (Preview in 12, standardized in 14)
String result = switch (day) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> "Weekday";
    case SATURDAY, SUNDAY -> "Weekend";
};
flowchart TD
    Input["day: DayOfWeek"] --> Switch{switch expr}
    Switch -->|MON..FRI| A["Weekday"]
    Switch -->|SAT, SUN| B["Weekend"]
    A --> Result["result: String"]
    B --> Result
Loading

Multi-statement arms use yield:

int numLetters = switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> 6;
    case TUESDAY -> 7;
    default -> {
        int len = day.toString().length();
        yield len;
    }
};

2️⃣ Collectors.teeing() (technically finalized in Java 12)

What: Run two collectors over the same stream and merge their results — no need for two separate passes.

record MinMax(double min, double max) {}

MinMax range = numbers.stream()
    .collect(Collectors.teeing(
        Collectors.minBy(Double::compareTo),
        Collectors.maxBy(Double::compareTo),
        (min, max) -> new MinMax(min.orElseThrow(), max.orElseThrow())
    ));

3️⃣ Compact Number Formatting

NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);
System.out.println(fmt.format(1_000));       // "1K"
System.out.println(fmt.format(1_000_000));   // "1M"
System.out.println(fmt.format(1_500));       // "2K" (rounds)

Why it matters: Great for dashboards — "1.2K views", "3.4M downloads" — without hand-rolling the logic.


4️⃣ File.mismatch(Path, Path)

Optional<Long> mismatch = Files.mismatch(path1, path2)
    .describeConstable(); // returns -1L wrapped if equal, else index of first mismatch

long result = Files.mismatch(path1, path2);
if (result == -1L) {
    System.out.println("Files are identical");
} else {
    System.out.println("Files differ at byte " + result);
}

5️⃣ Shenandoah GC (Experimental)

A low-pause-time garbage collector (contributed by Red Hat) aiming for pause times independent of heap size — an alternative to G1/ZGC for latency-sensitive apps.

java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -jar app.jar

💡 Best Practices

✅ Try switch expressions with --enable-preview in side projects to get ahead of Java 14
✅ Use teeing() instead of iterating a collection twice for two related aggregates
❌ Don't ship preview features (--enable-preview) to production — they can change before finalization


Clone this wiki locally