从 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