跳转至

从 JDK 8 到 17 的新特性

前面全书用 Java 8 风格,是因为国内公司和面试最常见。但 Java 在 8 之后进步巨大,很多新语法让它更像 JS/TS。这一章带你认识 JDK 17 里最有用的新特性。

新特性一览

特性 引入版本 对标前端 价值
var 局部类型推断 10 let 少写类型
文本块 """ 15 模板字符串 多行字符串
record 16 TS type 一行定义数据类
instanceof 模式匹配 16 — 强转一步到位
switch 表达式 14 — switch 能返回值
sealed 密封类 17 — 限定继承

1. var:少写类型

// JDK 8
String name = "Tom";
Map<String, List<Integer>> map = new HashMap<>();

// JDK 10+
var name = "Tom";                                   // 推断 String
var map = new HashMap<String, List<Integer>>();     // 推断右边类型

注意:var 只是"少写",类型仍编译期确定,不是动态类型。var x = 1; x = "a"; 还是报错。

2. 文本块:多行字符串

// JDK 8:拼接 + \n
String json = "{\n  \"name\": \"Tom\"\n}";

// JDK 15+:
var json = """
        {
          "name": "Tom"
        }
        """;

终于不用再转义引号、手动换行了。对标 JS 的反引号模板字符串。

3. record:一行定义数据类

// JDK 8:要写一大堆(字段、构造、getter、equals、hashCode)
class Point {
    private final int x, y;
    public Point(int x, int y) { this.x = x; this.y = y; }
    public int getX() { return x; }
    public int getY() { return y; }
    // 还要 equals/hashSet/toString...
}

// JDK 16+:一行
record Point(int x, int y) {}

访问器是 p.x() 不是 p.getX()``。写 DTO/VO 神器,对标 TS 的type Point = { x: number; y: number }`。

4. instanceof 模式匹配

// JDK 8
if (obj instanceof String) {
    String s = (String) obj;   // 还要手动强转
    System.out.println(s.length());
}

// JDK 16+
if (obj instanceof String s) {   // 直接绑定 s
    System.out.println(s.length());
}

5. switch 表达式

// JDK 8:只能用语句,要 break,不能返回值
String type;
switch (day) {
    case "MON": type = "工作日"; break;
    ...
}

// JDK 14+:表达式,箭头不穿透,能返回值
var type = switch (day) {
    case "MON", "TUE", "WED", "THU", "FRI" -> "工作日";
    case "SAT", "SUN" -> "周末";
    default -> "未知";
};

6. sealed:密封类

sealed interface Shape permits Circle, Rectangle {}
final class Circle implements Shape { ... }
final class Rectangle implements Shape { ... }

permits 限定只有 Circle/Rectangle 能实现 Shape。配合 instanceof 能做穷尽性检查——漏处理一个编译器会提醒。

完整可运行示例(release 17 编译)

package com.javaglm.advanced.ch36;

/**
 * 第 36 章 · 从 JDK 8 到 17 的新特性。
 * 本模块用 release 17 编译(覆盖基线的 8),演示现代语法。
 * 这些语法大多让 Java 更接近 JS/TS,对前端人友好。
 */
public class Jdk17Demo {

    public static void main(String[] args) {
        // 1. var:局部变量类型推断(JDK 10+)。对标 JS 的 let,编译期推断类型,仍是强类型。
        var name = "Tom";
        var count = 10;
        var list = new java.util.ArrayList<String>();
        list.add(name);
        System.out.println(name + ", " + count + ", list=" + list);

        // 2. 文本块(JDK 15):多行字符串。对标 JS 反引号模板字符串。
        var json = """
                {
                  "name": "Tom",
                  "age": 18
                }
                """;
        System.out.println(json);

        // 3. record(JDK 16):纯数据载体,一行搞定构造/getter/equals/hashCode。
        var p = new Point(3, 4);
        System.out.println("Point: " + p.x() + ", " + p.y());   // 访问器是 x() 不是 getX()

        // 4. instanceof 模式匹配(JDK 16):强转一步到位,不用再 (String) obj。
        Object obj = "hello";
        if (obj instanceof String s) {
            System.out.println("字符串长度 = " + s.length());
        }

        // 5. switch 表达式 + 箭头(JDK 14):能返回值、不穿透、可多值合并。
        var type = switch ("MON") {
            case "MON", "TUE", "WED", "THU", "FRI" -> "工作日";
            case "SAT", "SUN" -> "周末";
            default -> "未知";
        };
        System.out.println("类型 = " + type);

        // 6. sealed 密封类(JDK 17):限定谁能源码继承,配合 instanceof 穷尽处理。
        System.out.println("面积 = " + area(new Circle(2)));
    }

    /** record:一行定义不可变数据类。对标 TS 的 type Point = { x: number; y: number }。 */
    record Point(int x, int y) {
    }

    /** sealed + permits:只允许 Circle / Rectangle 实现 Shape。 */
    sealed interface Shape permits Circle, Rectangle {
    }

    static final class Circle implements Shape {
        final double r;
        Circle(double r) {
            this.r = r;
        }
    }

    static final class Rectangle implements Shape {
        final double w, h;
        Rectangle(double w, double h) {
            this.w = w;
            this.h = h;
        }
    }

    /** 用 instanceof 模式匹配处理 sealed 类型(JDK 17 稳定写法)。 */
    static double area(Shape shape) {
        if (shape instanceof Circle c) {
            return Math.PI * c.r * c.r;
        } else if (shape instanceof Rectangle r) {
            return r.w * r.h;
        }
        throw new IllegalArgumentException("未知形状");
    }
}

用不用这些

如果公司是 JDK 8,这些语法写不了(编译报错),但看懂是必须的——看开源代码、新项目都会遇到。等公司升级 JDK 17,你立刻能用上。面试也常问 "JDK 8 到 17 有哪些变化"。


:octicons-arrow-left-16: 上一章:部署上线 | 下一章:从 Spring Boot 2.7 到 3.x