Skip to content

Java 版本新特性

每次版本更新都带来惊喜,别再错过这些实用特性!🚀

🎯 为什么需要了解版本新特性

面试官:"你用过哪些 Java 新特性?" 答不上来?错过升职加薪的机会!💰


Java 8 新特性(LTS)

Java 史上最重要更新,函数式编程时代来临!

┌─────────────────────────────────────────────────────────────────┐
│                      Java 8 四大金刚                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   ☕ Lambda 表达式      →  告别匿名内部类                        │
│   🌊 Stream API         →  函数式数据处理                       │
│   🎁 Optional           →  跟 NPE 说拜拜                        │
│   📅 新日期时间 API     →  终于告别 Date                         │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

Lambda 表达式

💡 实战场景:告别啰嗦的匿名内部类

java
// ❌ 传统写法:5行代码
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello");
    }
}).start();

// ✅ Lambda 写法:1行搞定
new Thread(() -> System.out.println("Hello")).start();

// 排序对比
// ❌ 传统
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }
});

// ✅ Lambda
list.sort((s1, s2) -> s1.length() - s2.length());
// 还能更简洁
list.sort(Comparator.comparingInt(String::length));

Stream API

💡 实战场景:简化集合数据处理

java
List<User> users = getUsers();

// ❌ 传统写法:循环+判断+收集
List<String> names = new ArrayList<>();
for (User user : users) {
    if (user.getAge() > 20) {
        names.add(user.getName());
    }
}

// ✅ Stream 写法:一行搞定
List<String> names = users.stream()
    .filter(u -> u.getAge() > 20)      // 过滤
    .map(User::getName)                 // 转换
    .collect(Collectors.toList());      // 收集

// 高级操作
Map<Integer, List<User>> byAge = users.stream()
    .collect(Collectors.groupingBy(User::getAge));  // 分组

double avgAge = users.stream()
    .mapToInt(User::getAge)
    .average()
    .orElse(0);  // 平均年龄

🔥 面试点:Stream 和 Iterator 的区别?parallelStream 什么时候用?

java
// Stream vs Iterator
// 1. Stream 只能遍历一次
// 2. Stream 支持并行
// 3. Stream 是惰性执行(中间操作不执行,直到终端操作)

// parallelStream 适用场景
// ✅ 大数据量、纯计算、无状态
users.parallelStream()
    .filter(u -> complexCalculation(u))
    .collect(Collectors.toList());

// ❌ 不要用:有序需求、小数据量、IO 操作

Optional

💡 实战场景:优雅处理空值

java
// ❌ 传统写法:层层判断
String city = null;
if (user != null) {
    if (user.getAddress() != null) {
        city = user.getAddress().getCity();
    }
}
if (city == null) {
    city = "未知";
}

// ✅ Optional 写法
String city = Optional.ofNullable(user)
    .map(User::getAddress)
    .map(Address::getCity)
    .orElse("未知");

// 链式操作更强大
String result = Optional.ofNullable(user)
    .flatMap(User::getAddress)
    .flatMap(Address::getCity)
    .filter(c -> c.length() > 2)
    .orElseGet(() -> loadDefaultCity());

接口默认方法

💡 实战场景:向后兼容,不破坏现有接口

java
// Java 8 之前:接口新增方法,所有实现类都要改
// Java 8 之后:接口可以提供默认实现

public interface Animal {
    void eat();

    // 默认方法
    default void sleep() {
        System.out.println("动物睡觉");
    }

    // 静态方法
    static void printType() {
        System.out.println("这是动物");
    }
}

// 实现类只需要实现抽象方法
public class Dog implements Animal {
    @Override
    public void eat() {
        System.out.println("狗吃狗粮");
    }
}

Dog dog = new Dog();
dog.eat();    // 狗吃狗粮
dog.sleep();   // 动物睡觉(使用默认实现)
Animal.printType();  // 这是动物(静态方法调用)

Java 9 新特性

模块化时代来临,性能优化!

私有接口方法

💡 实战场景:解决接口默认方法代码复用

java
public interface MyService {
    default void method1() {
        // 重复代码
        log("method1 start");
        // 重复代码
        System.out.println("业务逻辑1");
        // 重复代码
        log("method1 end");
    }

    default void method2() {
        // 同样的重复代码
        log("method2 start");
        System.out.println("业务逻辑2");
        log("method2 end");
    }

    // Java 9 支持私有方法,抽取重复代码
    private void log(String message) {
        System.out.println(message);
    }
}

集合工厂方法

💡 实战场景:快速创建不可变集合

java
// ❌ 传统创建不可变集合
List<String> list = Collections.unmodifiableList(
    new ArrayList<>(Arrays.asList("a", "b", "c")));

// ✅ Java 9+ 工厂方法
List<String> list = List.of("a", "b", "c");
Set<Integer> set = Set.of(1, 2, 3);
Map<String, Integer> map = Map.of("a", 1, "b", 2);

// ⚠️ 注意:不可变集合不能增删改
list.add("d");  // UnsupportedOperationException

Stream 增强

💡 实战场景:takeWhile/dropWhile 简化逻辑

java
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// takeWhile:取满足条件的前缀
List<Integer> first = numbers.stream()
    .takeWhile(n -> n < 5)  // [1, 2, 3, 4]
    .collect(Collectors.toList());

// dropWhile:去掉满足条件的前缀
List<Integer> rest = numbers.stream()
    .dropWhile(n -> n < 5)  // [5, 6, 7, 8, 9, 10]
    .collect(Collectors.toList());

// iterate 重载:带终止条件
List<Integer> evens = Stream.iterate(0, n -> n + 2)
    .takeWhile(n -> n < 10)  // Java 9+
    .collect(Collectors.toList());  // [0, 2, 4, 6, 8]

Java 10 新特性

类型推断让代码更简洁!

var 类型推断

💡 实战场景:减少模板代码

java
// ❌ 啰嗦的泛型
ArrayList<String> list = new ArrayList<>();
Map<String, List<Map<String, Integer>>> complex = new HashMap<>();

// ✅ var 推断
var list = new ArrayList<String>();
var complex = new HashMap<String, List<Map<String, Integer>>>();

// 适用场景
var stream = list.stream();  // 类型由右侧推断
var user = new User("张三", 25);  // 调用构造方法推断

// ⚠️ var 的限制
var a;              // ❌ 不能声明未初始化
var b = () -> {};   // ❌ 不能推断 Lambda
var c = {1, 2, 3};  // ❌ 不能推断数组字面量

Java 11 新特性(LTS)

生产环境推荐版本,HTTP Client 终于转正!

HTTP Client

💡 实战场景:告别 HttpClientUtils,简化 HTTP 调用

java
// ❌ 传统:Apache HttpClient、OkHttp
HttpClient client = HttpClient.newHttpClient();

// ✅ Java 11+ 标准 HTTP Client(同步)
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users/1"))
    .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);

字符串增强

💡 实战场景:常用字符串操作更简便

java
String text = "  Hello World  ";

// 判断空白(比 isEmpty 更准确)
text.isBlank();        // true(包含空格)

// 去首尾空白
text.strip();          // "Hello World"
text.stripLeading();    // "Hello World  "
text.stripTrailing();   // "  Hello World"

// 行数统计
"line1\nline2\nline3".lines().count();  // 3

// 字符串重复
"abc".repeat(3);  // "abcabcabc"

// 格式化(Java 15+)
String name = "张三";
int age = 25;
String msg = STR."\{name} is \{age} years old.";

Java 14~17 新特性

语法糖大放送,代码更简洁!

Switch 表达式(Java 14 预览,Java 21 正式)

💡 实战场景:告别 break 地狱

java
// ❌ 传统 Switch:容易忘记 break
int result;
switch (day) {
    case MONDAY:
    case TUESDAY:
    case WEDNESDAY:
    case THURSDAY:
    case FRIDAY:
        result = 1;
        break;  // 忘记break会出bug
    case SATURDAY:
    case SUNDAY:
        result = 2;
        break;
    default:
        result = 0;
}

// ✅ Java 14+ Switch 表达式
int result = switch (day) {
    case MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY -> 1;
    case SATURDAY, SUNDAY -> 2;
    default -> 0;
};

// 更强大的用法
String label = switch (day) {
    case MONDAY, TUESDAY -> "工作日";
    case SATURDAY, SUNDAY -> "休息日";
    default -> {
        // 可以写复杂逻辑
        yield "未知";
    }
};

🔥 面试点:switch 表达式和 switch 语句的区别?

record 类型(Java 16 正式)

💡 实战场景:告别 Lombok,简化 POJO

java
// ❌ 传统 User 类:几十行代码
public class User {
    private final String name;
    private final int age;

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }

    @Override
    public boolean equals(Object o) { ... }
    @Override
    public int hashCode() { ... }
    @Override
    public String toString() { ... }
}

// ✅ Java 16+ record:一行搞定
public record User(String name, int age) {}

// 自动生成:构造方法、getter、toString、equals、hashCode
var user = new User("张三", 25);
user.name();   // getter 方法名是字段名,不是 getName()
user.age();    // 25
user.toString();  // User[name=张三, age=25]

// record 可以添加方法
public record User(String name, int age) {
    public String greet() {
        return "你好,我是" + name;
    }
}

🔥 面试点:record 和 class 的区别?record 的局限性?

sealed 类(Java 17 正式)

💡 实战场景:精确控制类的继承层次

java
// 传统:任何类都能继承你,无法控制
public class Shape { }  // 任何类都能 extends

// Java 17+ sealed:明确声明谁能继承
public sealed class Shape permits Circle, Rectangle, Square { }

// 必须声明为 final、sealed 或 non-sealed
public final class Circle extends Shape { }
public sealed class Rectangle extends Shape permits RoundRect { }
public non-sealed class Square extends Shape { }  // 允许任意继承

// 间接子类也要声明
public final class RoundRect extends Rectangle { }

🔥 面试点:sealed 类的应用场景?和枚举的区别?

Pattern Matching for instanceof(Java 16 正式)

💡 实战场景:告别强制类型转换

java
// ❌ 传统:先判断 instanceof,再强转
if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.length());
}

// ✅ Java 16+ Pattern Matching
if (obj instanceof String s) {
    System.out.println(s.length());  // 直接使用 s
}

// 结合 Switch(Java 21)
String format(Object obj) {
    return switch (obj) {
        case Integer i -> "整数: " + i;
        case String s && s.length() > 5 -> "长字符串: " + s;
        case String s -> "字符串: " + s;
        case null -> "空值";
        default -> "其他类型";
    };
}

Java 21 新特性(LTS)

虚拟线程开启并发新时代!

虚拟线程(正式)

💡 实战场景:告别线程池,简化并发编程

java
// ❌ 传统线程:创建成本高,数量有限
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 10000; i++) {
    executor.submit(() -> {
        // 每个任务一个线程?不,可能用线程池复用
        callHttpService();
    });
}

// ✅ Java 21+ 虚拟线程:轻量级,创建成本极低
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
    IntStream.range(0, 10000).forEach(i ->
        executor.submit(() -> callHTTPService())
    );
}

// 创建虚拟线程
Thread virtual = Thread.ofVirtual()
    .name("my-virtual-thread")
    .start(() -> System.out.println("Running in virtual thread"));
virtual.join();

// 自动门控(Structured Concurrency)
try (var scope = StructuredTaskScope.scope()) {
    Future<String> f1 = scope.fork(() -> callService1());
    Future<String> f2 = scope.fork(() -> callService2());

    scope.join();

    System.out.println(f1.resultNow() + " " + f2.resultNow());
}

🔥 面试点:虚拟线程和平台线程的区别?适用场景?

String Templates(预览)

💡 实战场景:字符串拼接更直观

java
// ❌ 传统拼接
String sql = "SELECT * FROM users WHERE id = " + userId +
    " AND name = '" + userName + "'";

// ✅ Java 21+ String Templates
String name = "张三";
int age = 25;

// STR 是内置模板处理器
String message = STR."Hello, \{name}! You are \{age} years old.";

// 模板表达式支持任何表达式
String greeting = STR."Your name has \{name.length()} characters.";

// 多行模板
String html = STR."""
    <html>
        <body>
            <p>Hello, \{name}!</p>
        </body>
    </html>
    """;

Java 22 新特性

2024年3月发布,Stream Gatherers 来了!

Stream Gatherers(预览)

💡 实战场景:自定义 Stream 中间操作

java
// Java 22+ Stream Gatherers
// 之前:复杂的自定义 Collector
// 现在:更直观的 Gatherer

// 窗口函数(按大小分组)
List<List<Integer>> windows = Stream.of(1, 2, 3, 4, 5)
    .gather(Gatherers.windowFixed(2))
    .collect(Collectors.toList());
// [[1, 2], [3, 4], [5]]

// 滑动窗口
List<List<Integer>> sliding = Stream.of(1, 2, 3, 4, 5)
    .gather(Gatherers.windowSliding(3))
    .collect(Collectors.toList());
// [[1, 2, 3], [2, 3, 4], [3, 4, 5]]

// 扫描(前缀累积)
List<Integer> scan = Stream.of(1, 2, 3, 4, 5)
    .gather(Gatherers.scan(() -> 0, Integer::sum))
    .collect(Collectors.toList());
// [0, 1, 3, 6, 10]

// 自定义 Gatherer
Gatherer<Integer, ?, List<Integer>> batch = Gatherer.of(
    () -> new ArrayList<Integer>(),
    Gatherer.Integrator.of((state, element, downstream) -> {
        state.add(element);
        if (state.size() == 3) {
            return downstream.push(new ArrayList<>(state)) && state.clear() == null;
        }
        return true;
    })
);

Unnamed Patterns and Variables(正式)

💡 实战场景:忽略不关心的变量

java
// ❌ 传统:必须给不用的变量起名
case Foo(String name, int _) -> process(name);

// ✅ Java 22+:用下划线忽略
case Foo(String name, int _) -> process(name);

// 循环中忽略索引
for (int i = 0, _ = init(); i < 10; i++) {
    doSomething();
}

// try-catch 忽略异常
try {
    riskyOperation();
} catch (Exception _) {
    log.warning("Operation failed");
}

Foreign Function & Memory API(预览)

💡 实战场景:告别 JNI,直接调用本地代码

java
// Java 22+ 简化版(之前版本较复杂)

// 调用 C 函数 qsort
Linker linker = Linker.nativeLinker();
SymbolLookup lookup = SymbolLookup.loaderLookup();

MemorySegment qsort = lookup.lookup("qsort").orElseThrow();
FunctionDescriptor qsortDescriptor = FunctionDescriptor.ofVoid(
    LINKER.allocate(arena, arraySize),
    ValueLayout.JAVA_INT,
    ValueLayout.JAVA_INT,
    LINKER.allocate(arena, 1)
);

// 更安全的内存操作
try (MemorySession session = MemorySession.openConfined()) {
    MemorySegment buffer = session.allocate(1024);
    // 直接操作堆外内存
}

Java 23 新特性

2024年9月发布,Stream Gatherers 转正!

Stream Gatherers(正式)

java
// Java 23 Stream Gatherers 正式版
import static java.util.stream.Gatherers.*;

// 管道操作更直观
List<Integer> result = Stream.of(1, 2, 3, 4, 5, 6)
    .gather(windowFixed(3))      // 每3个一组
    .gather(windowSliding(2))    // 滑动窗口
    .collect(Collectors.toList());

// fold(前缀累积,可变)
String concat = Stream.of("a", "b", "c")
    .gather(fold(() -> new StringBuilder(), StringBuilder::append))
    .map(StringBuilder::toString)
    .findFirst()
    .orElse("");

Implicitly Declared Classes and Instance Main Methods(正式)

💡 实战场景:快速脚本和入门示例

java
// Java 23+ 简化的 Hello World
// 无需 class 声明、public 修饰符
void main() {
    System.out.println("Hello, World!");
}

// 自动推断导入常用类
List.of(1, 2, 3)
    .forEach(System.out::println);

// 实例 main 访问实例成员
String message = "Hello";

void main() {
    System.out.println(message);  // 直接访问实例字段
}

新的 URL 解析方法

💡 实战场景:更安全的 URL 处理

java
// Java 23+ URI.create() vs URL.new URL()
// 新增更严格的解析

URI uri = URI.create("https://example.com/path?query=value");
String scheme = uri.getScheme();  // "https"

Java 24 新特性

2025年3月发布(如果已发布),预览特性持续演进。

预览特性演进

┌─────────────────────────────────────────────────────────────────┐
│                      Java 24 预览特性                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   📝 String Templates(第四预览)                                │
│      - STR模板处理器正式化                                      │
│      - 多行模板支持                                            │
│                                                                  │
│   🔧 Foreign Function & Memory API(正式)                       │
│      - 成熟的本地互操作能力                                     │
│                                                                  │
│   📦 Stream Gatherers(持续改进)                                │
│      - 性能优化                                                │
│                                                                  │
│   🔀 Structured Concurrency(持续改进)                           │
│      - 更好的并发编程模型                                       │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

可能的正式特性

java
// 如果 String Templates 转正
String name = "张三";
int age = 25;

// 模板表达式
String message = STR."我的名字是 \{name},今年 \{age} 岁";

// 多行模板(正式版可能支持)
String html = STR."""
    <div>
        <h1>\{name}</h1>
        <p>年龄:\{age}</p>
    </div>
    """;

// 模板处理器(自定义)
String xml = XML."""
    <user>
        <name>\{name}</name>
        <age>\{age}</age>
    </user>
    """;

Java 25+ 展望

Java 正在快速演进,未来值得期待!

┌─────────────────────────────────────────────────────────────────┐
│                      Java 未来方向                                │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   🚀 并发领域                                                   │
│      • 虚拟线程成熟化                                          │
│      • Structured Concurrency 完善                              │
│      • 并发集合增强                                            │
│                                                                  │
│   📦 性能优化                                                   │
│      • 持续改进 ZGC/Shenandoah                                 │
│      • 编译优化(AOT、Jaotc)                                   │
│      • 启动时间优化                                            │
│                                                                  │
│   🔧 开发体验                                                   │
│      • String Templates 正式化                                   │
│      • 简化语法持续改进                                        │
│      • 更好的 REPL 环境                                        │
│                                                                  │
│   🌐 互操作能力                                                 │
│      • Foreign Function API 成熟化                               │
│      • 更好的本地代码集成                                       │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

版本选择建议

┌─────────────────────────────────────────────────────────────────┐
│                      版本选择指南                                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│   🏆 Java 21 LTS  ⭐⭐⭐⭐⭐  当前生产环境首选                    │
│      • 虚拟线程正式版                                           │
│      • 成熟稳定,生态完善                                       │
│      • 新项目直接用                                            │
│                                                                  │
│   🚀 Java 22/23  ⭐⭐⭐    追新选择                             │
│      • 预览特性丰富                                            │
│      • 生产环境慎用                                            │
│      • 学习尝鲜不错                                            │
│                                                                  │
│   📦 Java 17 LTS  ⭐⭐⭐    保守升级                            │
│      • 旧项目还在用                                            │
│      • 升级优先级中等                                          │
│                                                                  │
│   ⚡ Java 11 LTS  ⭐⭐      legacy                              │
│      • 老项目维护                                              │
│      • 新项目不考虑                                            │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

总结

版本核心特性速查表

版本必会特性面试频率
Java 8Lambda、Stream、Optional⭐⭐⭐⭐⭐
Java 9List.of()、takeWhile⭐⭐⭐
Java 10var 类型推断⭐⭐⭐
Java 11HTTP Client、String.isBlank()⭐⭐⭐⭐
Java 14Switch 表达式⭐⭐⭐⭐
Java 16record、Pattern Matching⭐⭐⭐⭐
Java 17sealed 类⭐⭐⭐⭐
Java 21虚拟线程⭐⭐⭐⭐⭐
Java 22Stream Gatherers(预览)⭐⭐⭐
Java 23Stream Gatherers(正式)⭐⭐⭐⭐
Java 24预览特性演进⭐⭐⭐

⚠️ 易错点提醒

  1. var 不能用于字段、返回值、参数
  2. record 的 getter 是 name() 不是 getName()
  3. 虚拟线程不是银弹,CPU 密集型任务别用它
  4. Switch 表达式用 yield 返回值,不是 return
  5. Sealed 类子类必须声明 final/sealed/non-sealed
  6. Stream Gatherers 是 Java 22 预览,Java 23 才正式
  7. String Templates 一直是预览特性,生产环境慎用