痛点:老 instanceof 写法

if (obj instanceof Integer) {
    Integer n = (Integer) obj;      // 强转
    System.out.println(n * 2);
}

instanceof 检查 + cast 各一遍,啰嗦。

instanceof 模式(Java 16+)

if (obj instanceof Integer n) {     // 同时声明变量 n
    System.out.println(n * 2);
}

检查 + cast 一步。n 在 if 块内是 Integer 类型可直接用。

switch 模式匹配(Java 21+ 正式)

Object obj = ...;

String desc = switch (obj) {
    case Integer n -> "int: " + n;
    case Long l -> "long: " + l;
    case String s -> "string: " + s;
    case null -> "null";
    default -> "other: " + obj.getClass().getSimpleName();
};
  • 类型模式 + 自动 cast
  • null 是合法分支(不再抛 NPE)
  • 返回值
  • 编译器穷举性检查(配 sealed 用尤其香)

配 sealed = 代数数据类型

public sealed interface Shape permits Circle, Square, Triangle {}
public record Circle(double radius) implements Shape {}
public record Square(double side) implements Shape {}
public record Triangle(double base, double height) implements Shape {}

double area(Shape s) {
    return switch (s) {
        case Circle c -> Math.PI * c.radius() * c.radius();
        case Square sq -> sq.side() * sq.side();
        case Triangle t -> t.base() * t.height() / 2;
    };
}
// 不需要 default——编译器知道 sealed 子类型只这 3 个

加新子类型?比如 record Pentagon ...——所有 switch 没处理 Pentagon 的地方会编译错。逼着你处理 → 比文档约定可靠 100 倍。

解构模式(record patterns,Java 21+)

sealed interface Result<T> permits Ok, Err {}
record Ok<T>(T value) implements Result<T> {}
record Err<T>(String error) implements Result<T> {}

String describe(Result<User> r) {
    return switch (r) {
        case Ok<User>(User u) -> "found: " + u.name();   // 自动解构
        case Err<User>(String err) -> "error: " + err;
    };
}

case Ok<User>(User u) 同时检查类型 + 解构 record 字段。

嵌套也行:

record Pair<A, B>(A first, B second) {}

switch (pair) {
    case Pair<String, Integer>(String s, Integer i) -> ...;
    case Pair<String, Integer>(String s, null) -> ...;
}

case 守卫(when)

String classify(int n) {
    return switch (n) {
        case Integer i when i < 0 -> "负";
        case 0 -> "零";
        case Integer i when i < 10 -> "小";
        case Integer i -> "大";
    };
}

when 在模式后加条件——pattern 匹配 + when 守卫。

多值合并

String day(int d) {
    return switch (d) {
        case 1, 2, 3, 4, 5 -> "工作日";
        case 6, 7 -> "周末";
        default -> "?";
    };
}

, 分隔多个 case。

yield 用于块体

int v = switch (n) {
    case 1 -> 10;
    case 2 -> {
        System.out.println("computing");
        yield 20;       // 块体用 yield
    }
    default -> 0;
};

切实战:JSON-like 数据解构

sealed interface Json permits JsonObject, JsonArray, JsonString, JsonNumber, JsonBool, JsonNull {}
record JsonObject(Map<String, Json> fields) implements Json {}
record JsonArray(List<Json> items) implements Json {}
record JsonString(String value) implements Json {}
record JsonNumber(double value) implements Json {}
record JsonBool(boolean value) implements Json {}
record JsonNull() implements Json {}

String render(Json j) {
    return switch (j) {
        case JsonObject(Map<String, Json> fs) ->
            "{" + fs.entrySet().stream()
                .map(e -> "\"" + e.getKey() + "\":" + render(e.getValue()))
                .collect(Collectors.joining(",")) + "}";
        case JsonArray(List<Json> items) ->
            "[" + items.stream().map(this::render).collect(Collectors.joining(",")) + "]";
        case JsonString(String s) -> "\"" + s + "\"";
        case JsonNumber(double n) -> String.valueOf(n);
        case JsonBool(boolean b) -> String.valueOf(b);
        case JsonNull() -> "null";
    };
}

Sealed + record + pattern matching 三件套实现"代数数据类型"——以前 Java 写这种代码要 visitor pattern 上百行,现在几十行干完。

与 if-else 链对比

// ❌ 老写法
if (obj instanceof Integer) {
    Integer n = (Integer) obj;
    return "int: " + n;
} else if (obj instanceof String) {
    String s = (String) obj;
    return "string: " + s;
} else if (obj == null) {
    return "null";
} else {
    return "other";
}

// ✅ switch 表达式
return switch (obj) {
    case Integer n -> "int: " + n;
    case String s -> "string: " + s;
    case null -> "null";
    default -> "other";
};

紧凑 + 强类型 + 表达式(返回值)。

不支持的(Java 21 时点)

  • 数组 / List 解构(Java 22+ "通配模式"还在演化)
  • 字符串 / 数值 case 用模式(仍是字面量)
  • Unnamed patterns _——预览阶段

后续 Java 版本可能扩展。当前生产代码用上面这些就足够。

心智模型

学过 Rust / Scala / Kotlin 的 sealed + match——Java 21 的模式匹配是同样思路的实现。

  • 数据类:record
  • 封闭类型层级:sealed interface + permits
  • 分发:switch with pattern + yield + exhaustiveness check

→ 下一篇 Lambda + 函数式接口