# Java进阶新版本特性

# 1. Java 8 特性详解

# 1.1 函数式编程与 Lambda 表达式

设计思想转变: 传统的面向对象编程就像邮局寄信,必须填写完整的邮寄单(创建对象、实现接口)。Lambda 表达式则像快递扫码,只需"滴"一声就能完成身份验证。

传统匿名内部类写法:
Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello");
    }
};

Lambda 表达式写法:
Runnable r = () -> System.out.println("Hello");

结构对比:
传统:new 接口名() { 方法实现... }
Lambda: (参数) -> { 方法体 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

核心概念:

// 1. 无参数,无返回值
Runnable r1 = () -> System.out.println("Hello");

// 2. 一个参数,无返回值
Consumer<String> c = (name) -> System.out.println(name);

// 3. 省略参数括号(只有一个参数时)
Consumer<String> c = name -> System.out.println(name);

// 4. 多个参数,有返回值
Comparator<Integer> comp = (a, b) -> {
    System.out.println("比较:" + a + "和" + b);
    return a - b;
};

// 5. 方法引用(进一步简化)
List<String> names = Arrays.asList("Tom", "Jerry");
names.forEach(System.out::println);  // 静态方法引用
names.forEach(String::toUpperCase);  // 实例方法引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

应用场景:

// 集合排序
List<String> list = Arrays.asList("banana", "apple", "orange");
list.sort((s1, s2) -> s1.compareTo(s2));

// 线程创建
new Thread(() -> {
    for (int i = 0; i < 10; i++) {
        System.out.println(i);
    }
}).start();

// 事件处理
button.addActionListener(e -> System.out.println("按钮被点击"));
1
2
3
4
5
6
7
8
9
10
11
12
13

# 1.2 Stream API 流式处理

流水线作业思想: 传统集合操作像手工车间,每个工序独立完成。Stream 像自动化流水线,原料(数据)在流水线上依次经过各个工位(操作)。

传统方式处理集合:
原材料:[苹果, 香蕉, 橙子, 西瓜, 葡萄]
步骤:
1. 筛选长度>2的水果 → [苹果, 香蕉, 橙子, 西瓜, 葡萄]
2. 转换为大写 → [苹果, 香蕉, 橙子, 西瓜, 葡萄](中文不变)
3. 排序 → [西瓜, 葡萄, 苹果, 香蕉, 橙子]
4. 收集结果

Stream 处理:
stream()
    .filter(f -> f.length() > 2)    ← 筛选工位
    .map(String::toUpperCase)       ← 转换工位
    .sorted()                       ← 排序工位
    .collect(toList())              ← 包装工位
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Stream 操作分类:

Stream操作三阶段:
             中间操作(可多个)       终止操作(一个)
数据源 → 筛选/转换/排序... → 筛选/转换/排序... → 收集/统计

中间操作(懒加载):
filter  - 过滤不符合条件的元素
map     - 转换元素类型或值
sorted  - 排序
distinct- 去重
limit   - 限制数量
skip    - 跳过前N个

终止操作:
forEach - 遍历
collect - 收集为集合
count   - 计数
reduce  - 归约
anyMatch- 是否存在匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

代码示例:

List<String> fruits = Arrays.asList("apple", "banana", "orange", "watermelon");

// 1. 筛选和收集
List<String> longFruits = fruits.stream()
    .filter(f -> f.length() > 5)
    .collect(Collectors.toList());
// 结果:[banana, orange, watermelon]

// 2. 映射转换
List<Integer> lengths = fruits.stream()
    .map(String::length)
    .collect(Collectors.toList());
// 结果:[5, 6, 6, 10]

// 3. 排序
List<String> sorted = fruits.stream()
    .sorted()
    .collect(Collectors.toList());
// 结果:[apple, banana, orange, watermelon]

// 4. 并行处理提高性能
long count = fruits.parallelStream()
    .filter(f -> f.contains("a"))
    .count();

// 5. 分组统计
Map<Integer, List<String>> groupByLength = fruits.stream()
    .collect(Collectors.groupingBy(String::length));
// 结果:{5=[apple], 6=[banana, orange], 10=[watermelon]}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 1.3 Optional 类深度解析

空指针防护罩设计思想: Optional 就像一个智能包装盒,它明确告诉你:"盒子里可能有东西,也可能没有,但无论如何都不会让你直接摸到空指针。"

传统方式的风险路径:
用户 → 获取地址 → 获取城市 → 获取名称 → NPE!
    可能null   可能null   可能null

Optional 的安全路径:
用户 → Optional包装 → 安全获取地址 → 安全获取城市 → 安全获取名称
         ↓
     明确处理空值
1
2
3
4
5
6
7
8

Optional 使用模式:

// 1. 创建 Optional 对象
Optional<String> empty = Optional.empty();          // 空盒子
Optional<String> value = Optional.of("Hello");      // 非空盒子(值不能为null)
Optional<String> nullable = Optional.ofNullable(null); // 可为空的盒子

// 2. 安全获取值(避免直接get()导致NoSuchElementException)
String result = nullable.orElse("默认值");           // 为空时返回默认值
String result2 = nullable.orElseGet(() -> "生成的值"); // 为空时通过Supplier生成
String result3 = nullable.orElseThrow(() -> new RuntimeException("空值"));

// 3. 安全操作(链式调用)
User user = new User("Tom", 25);
String cityName = Optional.ofNullable(user)
    .map(User::getAddress)      // 如果user不为空,获取address
    .map(Address::getCity)      // 如果address不为空,获取city
    .map(City::getName)         // 如果city不为空,获取name
    .orElse("未知城市");         // 任何一步为空,返回默认值

// 4. 条件检查
Optional<String> opt = Optional.of("Hello");
opt.ifPresent(value -> System.out.println("值存在: " + value));

// 5. 过滤
Optional<String> filtered = opt.filter(s -> s.length() > 3);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

应用场景对比:

// 传统写法(危险)
public String getCityName(User user) {
    if (user != null) {
        Address address = user.getAddress();
        if (address != null) {
            City city = address.getCity();
            if (city != null) {
                return city.getName();
            }
        }
    }
    return "未知";
}

// Optional 写法(安全简洁)
public String getCityName(User user) {
    return Optional.ofNullable(user)
        .map(User::getAddress)
        .map(Address::getCity)
        .map(City::getName)
        .orElse("未知");
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 1.4 默认方法

接口升级兼容性设计: 默认方法就像是给接口这个"合同"增加了可选条款,老客户(已有实现类)可以继续使用原有条款,新客户可以选择使用新条款。

接口演进问题:
旧版本接口:        新需求:添加方法
    ↓                    ↓
实现类A、B、C...     需要全部修改实现类!

默认方法解决方案:
接口 {
    旧方法();
    default 新方法() {  // 提供默认实现
        // 默认逻辑
    }
}

实现类可以选择:
1. 不覆盖:使用默认实现
2. 覆盖:提供自己的实现
3. 强制覆盖:声明为抽象方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

代码示例:

// 1. 基本使用
interface Vehicle {
    void start();  // 传统抽象方法
    
    default void honk() {  // 默认方法
        System.out.println("嘟嘟嘟");
    }
    
    static void service() {  // 静态方法
        System.out.println("车辆维护服务");
    }
}

class Car implements Vehicle {
    @Override
    public void start() {
        System.out.println("汽车启动");
    }
    // 可以不实现 honk(),使用默认实现
}

// 2. 多继承冲突解决
interface A {
    default void hello() {
        System.out.println("A的hello");
    }
}

interface B {
    default void hello() {
        System.out.println("B的hello");
    }
}

class C implements A, B {
    @Override  // 必须覆盖,解决冲突
    public void hello() {
        A.super.hello();  // 显式调用A的默认方法
        System.out.println("C的hello");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# 1.5 新的日期时间 API

设计思想: 旧的 Date 和 Calendar 就像一本混乱的日记,各种时区、格式混在一起。新的日期时间 API 就像精密的瑞士手表,每个组件都职责清晰、不可变、线程安全。

旧API问题:
Date date = new Date();
// date 可变,非线程安全
// 月份从0开始(反人类)
// 没有时区处理
// 格式化与解析混乱

新API结构体系:
          TemporalAccessor(时间访问器)
                  ↑
          java.time 包核心结构
                  
    LocalDate    LocalTime    LocalDateTime
    (日期)        (时间)        (日期时间)
    
    ZonedDateTime    Instant      Duration
    (带时区)         (时间戳)     (时间段)
    
    Period          DateTimeFormatter
    (日期间隔)        (格式化)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

核心类使用:

// 1. 创建日期时间对象
LocalDate today = LocalDate.now();                    // 2023-10-01
LocalTime now = LocalTime.now();                      // 14:30:15.123
LocalDateTime current = LocalDateTime.now();          // 2023-10-01T14:30:15.123

// 2. 指定日期时间
LocalDate birthday = LocalDate.of(1990, Month.MAY, 15);
LocalTime meetingTime = LocalTime.of(14, 30);
LocalDateTime event = LocalDateTime.of(2023, 12, 25, 20, 0);

// 3. 日期计算(不可变对象,每次返回新对象)
LocalDate tomorrow = today.plusDays(1);
LocalDate nextWeek = today.plusWeeks(1);
LocalDate lastMonth = today.minusMonths(1);

// 4. 日期比较
boolean isAfter = today.isAfter(birthday);
boolean isBefore = today.isBefore(LocalDate.of(2024, 1, 1));
boolean isLeapYear = today.isLeapYear();

// 5. 格式化与解析
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = current.format(formatter);         // "2023-10-01 14:30:15"
LocalDateTime parsed = LocalDateTime.parse("2023-10-01 14:30:15", formatter);

// 6. 时区处理
ZonedDateTime zoned = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
ZonedDateTime newYorkTime = zoned.withZoneSameInstant(ZoneId.of("America/New_York"));

// 7. 时间差计算
Duration duration = Duration.between(startTime, endTime);
long hours = duration.toHours();
long minutes = duration.toMinutes();

Period period = Period.between(startDate, endDate);
int years = period.getYears();
int months = period.getMonths();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 1.6 其他重要特性

# 1.6.1 类型注解和重复注解

代码示例:

// 1. 类型注解(可用于任何类型使用的地方)
@NotNull String name = getName();  // 编译器检查非空
List<@Email String> emails;        // 集合元素类型注解

// 2. 重复注解(同一个注解使用多次)
@Role("admin")
@Role("user")
class User {
    // ...
}

// 定义可重复注解
@Repeatable(Roles.class)
@interface Role {
    String value();
}

@interface Roles {
    Role[] value();  // 容器注解
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 1.6.2 StampedLock 锁优化

乐观读锁设计: StampedLock 就像图书馆的智能借阅系统,大部分读者可以快速浏览(乐观读),只有在真正需要修改时才上锁。

StampedLock 三种模式:
1. 写锁:独占锁,类似 ReentrantLock.writeLock()
2. 悲观读锁:共享锁,类似 ReentrantLock.readLock()
3. 乐观读:无锁读取,先获取戳记,验证时检查是否被修改

工作流程:
   获取乐观读戳记 → 读取数据 → 验证戳记 → 有效则使用,无效则升级锁
         ↓                             ↓
      快速路径                     回退路径
1
2
3
4
5
6
7
8
9

代码示例:

class Point {
    private double x, y;
    private final StampedLock sl = new StampedLock();
    
    // 写操作使用写锁
    void move(double deltaX, double deltaY) {
        long stamp = sl.writeLock();  // 获取写锁
        try {
            x += deltaX;
            y += deltaY;
        } finally {
            sl.unlockWrite(stamp);    // 释放写锁
        }
    }
    
    // 读操作使用乐观读
    double distanceFromOrigin() {
        long stamp = sl.tryOptimisticRead();  // 获取乐观读戳记
        double currentX = x, currentY = y;
        
        if (!sl.validate(stamp)) {     // 检查期间是否有写操作
            stamp = sl.readLock();     // 升级为悲观读锁
            try {
                currentX = x;
                currentY = y;
            } finally {
                sl.unlockRead(stamp);  // 释放读锁
            }
        }
        return Math.sqrt(currentX * currentX + currentY * currentY);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 1.6.3 JRE 精简和 PermGen 移除

Java 8 内存模型变化:
Java 7 及以前:                     Java 8:
┌─────────────────┐               ┌─────────────────┐
│  堆(Heap)       │               │  堆(Heap)       │
│  - Eden         │               │  - Eden         │
│  - Survivor     │               │  - Survivor     │
│  - Old Gen      │               │  - Old Gen      │
├─────────────────┤               ├─────────────────┤
│  非堆内存        │               │  非堆内存        │
│  - PermGen      │ ← 移除        │  - Metaspace    │ ← 新增
│  (方法区)        │               │  (元空间)        │
├─────────────────┤               ├─────────────────┤
│  JVM自身使用     │               │  JVM自身使用     │
│  - 代码缓存      │               │  - 代码缓存      │
└─────────────────┘               └─────────────────┘

关键改进:
1. PermGen → Metaspace
   - 位置:从JVM内存移到本地内存
   - 大小:自动扩展,无固定上限
   - 回收:随ClassLoader回收,减少Full GC
   
2. JRE精简:移除了很少使用的功能,减小安装包
   - 移除Java DB (Derby)
   - 移除JavaFX(单独提供)
   - 移除VisualVM(单独提供)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 2. Java 8 到 Java 11 重要特性

# 2.1 局部变量类型推断 (var)

设计思想: var 关键字就像智能标签,编译器能根据"内容"推断"容器"类型,让代码更简洁但不损失类型安全。

// Java 10+ 使用 var
var list = new ArrayList<String>();      // 推断为 ArrayList<String>
var stream = list.stream();              // 推断为 Stream<String>
var map = new HashMap<String, Integer>(); // 推断为 HashMap<String, Integer>

// 等价于传统写法
ArrayList<String> list = new ArrayList<String>();
Stream<String> stream = list.stream();
HashMap<String, Integer> map = new HashMap<String, Integer>();

// 限制:必须初始化,不能为null,不能用于lambda
var nullVar = null;          // 编译错误:不能推断类型
var lambda = () -> "hello";  // 编译错误:不能用于lambda
1
2
3
4
5
6
7
8
9
10
11
12
13

# 2.2 HTTP Client API (标准化)

代码示例:

// Java 11 引入标准 HTTP Client
import java.net.http.*;
import java.net.URI;
import java.time.Duration;

HttpClient client = HttpClient.newBuilder()
    .connectTimeout(Duration.ofSeconds(10))
    .version(HttpClient.Version.HTTP_2)      // 支持HTTP/2
    .build();

// 同步请求
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/data"))
    .header("Content-Type", "application/json")
    .GET()
    .build();

HttpResponse<String> response = client.send(request, 
    HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());

// 异步请求
client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
    .thenApply(HttpResponse::body)
    .thenAccept(System.out::println)
    .join();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 2.3 字符串增强

// 1. 重复字符串
String repeated = "Java ".repeat(3);  // "Java Java Java "

// 2. 判断空白字符串
boolean blank1 = " ".isBlank();       // true(空格、制表符等)
boolean blank2 = "".isBlank();        // true
boolean empty = "".isEmpty();         // true(只有isEmpty时为空)

// 3. 去除首尾空白(支持Unicode)
String stripped = "  hello  ".strip();      // "hello"
String leading = "  hello  ".stripLeading(); // "hello  "
String trailing = "  hello  ".stripTrailing(); // "  hello"

// 4. 按行分割为Stream
String multiline = "第一行\n第二行\n第三行";
multiline.lines()                     // 返回Stream<String>
    .filter(line -> !line.isBlank())
    .forEach(System.out::println);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 2.4 单文件源代码程序

设计思想: 让Java像脚本语言一样可以直接运行单个文件,无需先编译再运行。

// HelloWorld.java(可以直接运行)
#!/usr/bin/env java --source 11

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

// 运行方式:
// java HelloWorld.java
// 无需先编译:javac HelloWorld.java
1
2
3
4
5
6
7
8
9
10
11
12

# 3. Java 11 到 Java 17 重要特性

# 3.1 密封类 (Sealed Classes)

设计思想: 密封类就像有限制的继承体系,明确指定哪些类可以继承,防止随意扩展,增强代码安全性。

// Java 17 密封类
public sealed class Shape 
    permits Circle, Rectangle, Triangle {  // 只允许这三个子类
    // 父类定义
}

// 子类必须声明为 final、sealed 或 non-sealed
public final class Circle extends Shape { /* ... */ }
public non-sealed class Rectangle extends Shape { /* ... */ }
public sealed class Triangle extends Shape permits Equilateral { /* ... */ }
public final class Equilateral extends Triangle { /* ... */ }

// 模式匹配中使用
double area = switch (shape) {
    case Circle c -> Math.PI * c.radius() * c.radius();
    case Rectangle r -> r.width() * r.height();
    case Triangle t -> 0.5 * t.base() * t.height();
    // 不需要default,因为所有子类都已处理
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 3.2 模式匹配 (Pattern Matching)

代码演进:

// Java 16 前:繁琐的类型检查和转换
if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.length());
}

// Java 16+:模式匹配简化
if (obj instanceof String s) {  // 同时检查和转换
    System.out.println(s.length());
}

// switch 表达式 + 模式匹配 (Java 17预览)
String formatted = switch (obj) {
    case Integer i -> String.format("整数: %d", i);
    case Long l -> String.format("长整数: %d", l);
    case Double d -> String.format("小数: %f", d);
    case String s -> String.format("字符串: %s", s);
    default -> "其他类型";
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 3.3 文本块 (Text Blocks)

多行字符串简化:

// 传统方式(繁琐)
String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, world!</p>\n" +
              "    </body>\n" +
              "</html>\n";

// Java 15+ 文本块(更清晰)
String html = """
    <html>
        <body>
            <p>Hello, world!</p>
        </body>
    </html>
    """;
    
// JSON 示例
String json = """
    {
        "name": "张三",
        "age": 25,
        "hobbies": ["阅读", "编程", "音乐"]
    }
    """;
    
// 格式化控制
String text = """
    姓名: %s
    年龄: %d
    """.formatted("李四", 30);  // formatted 方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 3.4 Record 类 (数据载体类)

设计思想: Record 就像数据表的行记录,自动生成构造器、访问器、equals、hashCode、toString 方法,专注于数据传输。

传统 POJO 类:              Record 类:
public class Person {       public record Person(
    private String name;        String name,
    private int age;            int age,
                                String address
    // 构造器、getter、setter   ) {}
    // equals、hashCode
    // toString
    // 大量样板代码
}
1
2
3
4
5
6
7
8
9
10

代码示例:

// 1. 定义 Record
public record Person(String name, int age, String address) {
    // 可以添加自定义方法
    public String greeting() {
        return "Hello, I'm " + name;
    }
    
    // 可以重写自动生成的方法
    @Override
    public String toString() {
        return name + " (" + age + "岁)";
    }
}

// 2. 使用 Record
Person p1 = new Person("张三", 25, "北京");
Person p2 = new Person("张三", 25, "北京");

System.out.println(p1.name());     // 访问器:张三
System.out.println(p1.age());      // 25
System.out.println(p1.equals(p2)); // true(自动实现)
System.out.println(p1);            // 张三 (25岁)

// 3. 解构模式 (Java 21预览)
if (p1 instanceof Person(String name, int age, String address)) {
    System.out.println(name + "住在" + address);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 4. Java 17 到 Java 21 重要特性

# 4.1 虚拟线程 (Virtual Threads)

设计思想: 传统线程像真实员工,创建成本高、数量有限。虚拟线程像机器人,创建快、数量多,由少量平台线程调度执行。

传统线程模型:             虚拟线程模型:
┌─────────────┐           ┌─────────────┐
│ 平台线程1    │           │ 平台线程1    │
│ ┌─────────┐ │           │ ┌─────────┐ │
│ │ 任务A    │ │           │ │虚拟线程A│ │
│ └─────────┘ │           │ └─────────┘ │
└─────────────┘           │ ┌─────────┐ │
┌─────────────┐           │ │虚拟线程B│ │
│ 平台线程2    │           │ └─────────┘ │
│ ┌─────────┐ │           │ ┌─────────┐ │
│ │ 任务B    │ │           │ │虚拟线程C│ │
│ └─────────┘ │           │ └─────────┘ │
└─────────────┘           └─────────────┘
          创建10K线程 → 崩溃    创建10K虚拟线程 → 轻松
1
2
3
4
5
6
7
8
9
10
11
12
13
14

代码示例:

// Java 21 虚拟线程
// 1. 创建虚拟线程
Thread virtualThread = Thread.ofVirtual()
    .name("virtual-thread-", 0)
    .start(() -> {
        System.out.println("Hello from virtual thread");
    });

// 2. 使用 ExecutorService
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10_000).forEach(i -> {
        executor.submit(() -> {
            Thread.sleep(Duration.ofSeconds(1));
            System.out.println(i);
            return i;
        });
    });
} // executor.close() 自动调用

// 3. 结构化并发 (Java 21预览)
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
    Future<String> user = scope.fork(() -> fetchUser());
    Future<Integer> order = scope.fork(() -> fetchOrder());
    
    scope.join();           // 等待所有任务
    scope.throwIfFailed();  // 传播异常
    
    System.out.println("User: " + user.resultNow());
    System.out.println("Order: " + order.resultNow());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

# 4.2 序列集合 (Sequenced Collections)

设计思想: 为集合接口添加明确的顺序操作,提供统一的 first/last 访问方法。

// Java 21 序列集合
// SequencedCollection, SequencedSet, SequencedMap

// 1. SequencedCollection (有序集合)
SequencedCollection<String> seq = new ArrayList<>();
seq.add("A");
seq.add("B");
seq.add("C");

System.out.println(seq.getFirst());  // "A"
System.out.println(seq.getLast());   // "C"

seq.addFirst("Start");  // [Start, A, B, C]
seq.addLast("End");     // [Start, A, B, C, End]

// 2. SequencedMap (有序映射)
SequencedMap<Integer, String> map = new LinkedHashMap<>();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");

System.out.println(map.firstEntry());  // 1=One
System.out.println(map.lastEntry());   // 3=Three

// 反向视图
SequencedMap<Integer, String> reversed = map.reversed();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 4.3 switch 模式匹配增强

代码示例:

// Java 21 switch 模式匹配
Object obj = "Hello";

// 1. 类型模式 + 守卫条件
String result = switch (obj) {
    case null -> "null";
    case String s when s.length() > 5 -> "长字符串: " + s;
    case String s -> "字符串: " + s;
    case Integer i -> "整数: " + i;
    case int[] array when array.length == 0 -> "空数组";
    case int[] array -> "数组长度: " + array.length;
    default -> "其他";
};

// 2. Record 模式匹配
record Point(int x, int y) {}
record Circle(Point center, int radius) {}

Object shape = new Circle(new Point(0, 0), 10);

if (shape instanceof Circle(Point center, int radius)) {
    System.out.println("圆心: (" + center.x() + "," + center.y() + ")");
}

// 3. 嵌套模式匹配
double area = switch (shape) {
    case Circle(Point(var x, var y), var r) -> Math.PI * r * r;
    case Rectangle(Point p1, Point p2) -> 
        Math.abs((p2.x() - p1.x()) * (p2.y() - p1.y()));
    default -> 0;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 4.4 分代 ZGC (Generational ZGC)

垃圾回收优化:

// Java 21 ZGC 分代收集
// 启动参数
// -XX:+UseZGC -XX:+ZGenerational

// ZGC 分代优势:
// 年轻代:高频收集,快速回收短命对象
// 老年代:低频收集,减少停顿时间

// 性能对比:
// 吞吐量提升:10-30%
// 最大停顿时间:<1ms
1
2
3
4
5
6
7
8
9
10
11

# 5. Java 22+ 新特性概述

# 5.1 字符串模板 (预览)

// Java 22 字符串模板(预览)
import static java.lang.StringTemplate.*;

// 1. STR 模板处理器
String name = "Alice";
int age = 25;
String message = STR."Hello, \{name}! You are \{age} years old.";
// 结果:Hello, Alice! You are 25 years old.

// 2. FMT 格式化模板
double price = 19.99;
String formatted = FMT."价格: %8.2f\{price}";
// 结果:价格:    19.99

// 3. 自定义模板处理器
StringTemplate st = RAW."用户 \{name} 年龄 \{age}";
String result = st.process(StringTemplate::interpolate);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 5.2 未命名变量和模式

// Java 22 未命名变量
// 1. 忽略不需要的变量
try {
    int result = Integer.parseInt("123");
} catch (NumberFormatException _) {  // 使用 _ 忽略异常变量
    System.out.println("解析失败");
}

// 2. 忽略不需要的lambda参数
list.forEach(_ -> System.out.println("元素"));

// 3. 忽略记录组件
record Person(String name, int age, String _) {}  // 忽略地址

// 4. 模式匹配中忽略部分
if (obj instanceof Point(int x, int _)) {  // 忽略y坐标
    System.out.println("x = " + x);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 5.3 结构化并发 (正式)

// Java 22 结构化并发(正式)
Response handle() throws ExecutionException, InterruptedException {
    try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
        Future<String> user = scope.fork(() -> findUser());
        Future<Integer> order = scope.fork(() -> fetchOrder());
        
        scope.join();            // 等待两个任务
        scope.throwIfFailed();   // 如果失败则抛出异常
        
        return new Response(user.resultNow(), order.resultNow());
    }
    // 自动取消未完成的任务
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 5.4 Vector API (第七次孵化)

// Java 22 Vector API(用于向量计算)
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_PREFERRED;

void vectorComputation(float[] a, float[] b, float[] c) {
    for (int i = 0; i < a.length; i += SPECIES.length()) {
        var m = SPECIES.indexInRange(i, a.length);
        
        FloatVector va = FloatVector.fromArray(SPECIES, a, i, m);
        FloatVector vb = FloatVector.fromArray(SPECIES, b, i, m);
        
        FloatVector vc = va.mul(va)  // a²
                          .add(vb.mul(vb))  // + b²
                          .sqrt();          // √(a²+b²)
        
        vc.intoArray(c, i, m);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 6. 各版本关键特性总结

# 6.1 版本演进路线图

Java 版本演进(LTS版本重点):
┌─────────┬─────────┬─────────┬─────────┬─────────┐
│ Java 8  │ Java 11 │ Java 17 │ Java 21 │ Java 25 │
│ (2014)  │ (2018)  │ (2021)  │ (2023)  │ (2025?) │
├─────────┼─────────┼─────────┼─────────┼─────────┤
│ Lambda  │ var     │ 密封类  │虚拟线程 │  待定   │
│ Stream  │HTTP客户端│ Record │结构化并发│         │
│ Optional│ 字符串增强│文本块  │序列集合 │         │
│ 新日期API│        │模式匹配 │分代ZGC  │         │
│ 默认方法 │        │        │        │         │
└─────────┴─────────┴─────────┴─────────┴─────────┘
1
2
3
4
5
6
7
8
9
10
11

# 6.2 升级建议

从 Java 8 升级:

  1. 先升级到 Java 11 LTS

    • 语法:使用 var 简化类型声明
    • API:使用新的 HTTP Client、字符串方法
    • 工具:使用单文件源代码执行
  2. 再升级到 Java 17 LTS

    • 语法:使用 Record、文本块、密封类
    • 模式:使用模式匹配简化代码
    • 性能:使用 ZGC 改进垃圾回收
  3. 最后升级到 Java 21+

    • 并发:使用虚拟线程处理高并发
    • 集合:使用序列集合统一API
    • 开发:使用结构化并发管理任务

# 6.3 特性应用场景

根据需求选择特性:

// 高并发场景:Java 21+ 虚拟线程
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    // 处理大量并发任务
}

// 数据处理场景:Java 8+ Stream API
data.stream()
    .filter(...)
    .map(...)
    .collect(...);

// API开发场景:Java 11+ HTTP Client
HttpClient.newHttpClient().send(...);

// 数据模型场景:Java 16+ Record
public record User(String name, int age) {}

// 字符串处理:Java 15+ 文本块
String json = """
    { "name": "value" }
    """;

// 模式匹配:Java 17+ switch表达式
String result = switch (obj) {
    case String s -> "字符串";
    case Integer i -> "整数";
    default -> "其他";
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 7. 实践示例:综合运用新特性

# 7.1 现代化 Java 代码示例

// 综合使用 Java 8-21 特性的示例
import java.net.http.*;
import java.net.URI;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;

public class ModernJavaExample {
    
    // 使用 Record 定义数据模型
    public record User(String id, String name, int age, List<String> roles) {}
    
    // 使用密封类定义操作类型
    public sealed interface Operation 
        permits CreateOp, UpdateOp, DeleteOp {}
    
    public record CreateOp(User user) implements Operation {}
    public record UpdateOp(String id, User user) implements Operation {}
    public record DeleteOp(String id) implements Operation {}
    
    public static void main(String[] args) {
        // 使用虚拟线程执行器
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            
            // 并行处理用户数据
            List<Future<User>> futures = IntStream.range(0, 10)
                .mapToObj(i -> executor.submit(() -> fetchUser(i)))
                .toList();
            
            // 收集结果
            List<User> users = futures.stream()
                .map(future -> {
                    try {
                        return future.get();
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                })
                .filter(user -> user.age() >= 18)
                .sorted(Comparator.comparing(User::name))
                .toList();
            
            // 使用模式匹配处理操作
            Operation op = new CreateOp(new User("1", "Alice", 25, List.of("admin")));
            
            String result = switch (op) {
                case CreateOp(User user) -> 
                    STR."创建用户: \{user.name()},角色: \{String.join(",", user.roles())}";
                case UpdateOp(String id, User user) -> 
                    STR."更新用户 \{id}: \{user.name()}";
                case DeleteOp(String id) -> 
                    STR."删除用户: \{id}";
            };
            
            System.out.println(result);
            
            // 使用 HTTP Client 调用外部API
            HttpClient client = HttpClient.newHttpClient();
            HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.example.com/users"))
                .header("Content-Type", "application/json")
                .build();
            
            client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                .thenApply(HttpResponse::body)
                .thenAccept(System.out::println)
                .join();
        }
    }
    
    private static User fetchUser(int id) {
        // 模拟从数据库获取用户
        return new User(
            String.valueOf(id),
            "User" + id,
            20 + id,
            List.of("user")
        );
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80

# 7.2 性能优化示例

// 使用新特性优化性能
public class PerformanceOptimization {
    
    // 1. 使用 Record 减少内存占用
    public record EfficientData(int id, String name, double value) {}
    
    // 2. 使用虚拟线程处理IO密集型任务
    public CompletableFuture<List<String>> fetchUrls(List<String> urls) {
        try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
            List<Future<String>> futures = urls.stream()
                .map(url -> scope.fork(() -> fetchUrl(url)))
                .toList();
            
            scope.join();
            scope.throwIfFailed();
            
            return CompletableFuture.completedFuture(
                futures.stream()
                    .map(Future::resultNow)
                    .toList()
            );
        } catch (Exception e) {
            return CompletableFuture.failedFuture(e);
        }
    }
    
    // 3. 使用 Vector API 进行数值计算优化
    public void vectorizedComputation(float[] array) {
        var species = FloatVector.SPECIES_PREFERRED;
        
        for (int i = 0; i < array.length; i += species.length()) {
            var mask = species.indexInRange(i, array.length);
            var vector = FloatVector.fromArray(species, array, i, mask);
            
            // 向量化运算
            var result = vector.mul(vector).add(vector).sqrt();
            result.intoArray(array, i, mask);
        }
    }
    
    private String fetchUrl(String url) {
        // 模拟HTTP请求
        return "Response from " + url;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45

# 总结

Java 从版本 8 到 25 的演进,体现了从面向对象到函数式、从重量级到轻量级、从复杂到简洁的转变。关键趋势包括:

  1. 简洁性:var、Record、文本块等减少样板代码
  2. 安全性:密封类、Optional 等增强类型安全
  3. 并发性:虚拟线程、结构化并发改进并发编程
  4. 性能:ZGC、Vector API 等提升运行时性能
  5. 现代化:模式匹配、HTTP Client 等提供现代编程体验

建议根据项目需求选择合适的版本升级,优先采用 LTS 版本(8、11、17、21),逐步引入新特性改进代码质量和性能。

最近更新: 2026/1/21
 |  Copyright © -Present Kelsen All Rights Reserved. | Author KelsenJing