跳转至

从 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