Appearance
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"); // UnsupportedOperationExceptionStream 增强
💡 实战场景: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 8 | Lambda、Stream、Optional | ⭐⭐⭐⭐⭐ |
| Java 9 | List.of()、takeWhile | ⭐⭐⭐ |
| Java 10 | var 类型推断 | ⭐⭐⭐ |
| Java 11 | HTTP Client、String.isBlank() | ⭐⭐⭐⭐ |
| Java 14 | Switch 表达式 | ⭐⭐⭐⭐ |
| Java 16 | record、Pattern Matching | ⭐⭐⭐⭐ |
| Java 17 | sealed 类 | ⭐⭐⭐⭐ |
| Java 21 | 虚拟线程 | ⭐⭐⭐⭐⭐ |
| Java 22 | Stream Gatherers(预览) | ⭐⭐⭐ |
| Java 23 | Stream Gatherers(正式) | ⭐⭐⭐⭐ |
| Java 24 | 预览特性演进 | ⭐⭐⭐ |
⚠️ 易错点提醒:
- var 不能用于字段、返回值、参数
- record 的 getter 是
name()不是getName() - 虚拟线程不是银弹,CPU 密集型任务别用它
- Switch 表达式用
yield返回值,不是return - Sealed 类子类必须声明
final/sealed/non-sealed - Stream Gatherers 是 Java 22 预览,Java 23 才正式
- String Templates 一直是预览特性,生产环境慎用