Java 新版本特性 (Java New Version Features)¶
从Java 8到Java 21的重要新特性,紧跟Java发展趋势
目录¶
- Java 8 (2014) - LTS
- Java 9 (2017)
- Java 10 (2018)
- Java 11 (2018) - LTS
- Java 12-16 (2019-2021)
- Java 17 (2021) - LTS
- Java 18-20 (2022-2023)
- Java 21 (2023) - LTS
- 版本选择建议
- 面试高频问题
Java 8 (2014) - LTS¶
⭐⭐⭐⭐⭐ 革命性更新,最重要的版本之一
1. Lambda表达式 (Lambda Expressions)¶
// 传统方式
List<String> list = Arrays.asList("A", "B", "C");
Collections.sort(list, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
return s1.compareTo(s2);
}
});
// Lambda方式
Collections.sort(list, (s1, s2) -> s1.compareTo(s2));
2. Stream API¶
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
// 传统方式:求偶数的平方和
int sum = 0;
for (Integer num : numbers) {
if (num % 2 == 0) {
sum += num * num;
}
}
// Stream方式
int streamSum = numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.reduce(0, Integer::sum);
3. Optional类¶
// 传统null检查
public String getUserName(User user) {
if (user != null) {
return user.getName();
}
return "Unknown";
}
// Optional方式
public String getUserName(Optional<User> user) {
return user.map(User::getName).orElse("Unknown");
}
4. 接口默认方法 (Default Methods)¶
public interface Vehicle {
// 抽象方法
void start();
// 默认方法(Java 8+)
default void stop() {
System.out.println("车辆停止");
}
// 静态方法(Java 8+)
static void checkEngine() {
System.out.println("检查引擎");
}
}
class Car implements Vehicle {
@Override
public void start() {
System.out.println("汽车启动");
}
// 可以选择重写默认方法
@Override
public void stop() {
System.out.println("汽车停止");
}
}
5. 新的日期时间API (java.time)¶
// 旧API的问题:线程不安全,设计混乱
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// 新API:不可变、线程安全
LocalDate today = LocalDate.now();
LocalDate birthday = LocalDate.of(2000, 1, 1);
LocalDateTime now = LocalDateTime.now();
ZonedDateTime zonedNow = ZonedDateTime.now();
// 日期计算
LocalDate nextWeek = today.plusWeeks(1);
LocalDate lastMonth = today.minusMonths(1);
// 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = now.format(formatter);
// 解析
LocalDateTime parsed = LocalDateTime.parse("2025-10-28 10:30:00", formatter);
// 计算时间差
long daysBetween = ChronoUnit.DAYS.between(birthday, today);
System.out.println("距离生日: " + daysBetween + "天");
6. 方法引用 (Method References)¶
7. 重复注解 (Repeating Annotations)¶
@Repeatable(Schedules.class)
@interface Schedule {
String day();
}
@interface Schedules {
Schedule[] value();
}
@Schedule(day = "Monday")
@Schedule(day = "Wednesday")
public class Task {
}
Java 9 (2017)¶
1. 模块化系统 (Project Jigsaw)¶
// module-info.java
module com.example.myapp {
requires java.sql;
requires com.example.utils;
exports com.example.myapp.api;
}
2. JShell (交互式编程工具)¶
3. 集合工厂方法¶
// Java 8及之前
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");
list.add("C");
List<String> immutableList = Collections.unmodifiableList(list);
// Java 9+
List<String> list = List.of("A", "B", "C"); // 不可变
Set<String> set = Set.of("A", "B", "C");
Map<String, Integer> map = Map.of("A", 1, "B", 2, "C", 3);
// Map.ofEntries()用于更多键值对
Map<String, Integer> bigMap = Map.ofEntries(
Map.entry("A", 1),
Map.entry("B", 2),
Map.entry("C", 3)
);
4. 私有接口方法¶
public interface MyInterface {
default void method1() {
commonLogic();
}
default void method2() {
commonLogic();
}
// Java 9+: 私有方法
private void commonLogic() {
System.out.println("通用逻辑");
}
}
5. Stream API增强¶
// takeWhile() - 从头取元素直到条件为false
Stream.of(1, 2, 3, 4, 5, 6)
.takeWhile(n -> n < 4)
.forEach(System.out::println); // 1, 2, 3
// dropWhile() - 从头丢弃元素直到条件为false
Stream.of(1, 2, 3, 4, 5, 6)
.dropWhile(n -> n < 4)
.forEach(System.out::println); // 4, 5, 6
// ofNullable() - 创建可能为null的Stream
Stream<String> stream = Stream.ofNullable(null);
Java 10 (2018)¶
1. 局部变量类型推断 (var)¶
// Java 9及之前
Map<String, List<String>> map = new HashMap<>();
List<String> list = new ArrayList<>();
// Java 10+: var关键字
var map = new HashMap<String, List<String>>();
var list = new ArrayList<String>();
var str = "Hello"; // String类型
var num = 10; // int类型
// 注意:var不能用于
// - 方法参数
// - 方法返回类型
// - 成员变量
// - 初始值为null的变量
// ✅ 适用场景
for (var item : list) {
System.out.println(item);
}
try (var input = new FileInputStream("file.txt")) {
// ...
}
// ❌ 不适用场景
// var x = null; // 编译错误
// var[] array = {1, 2, 3}; // 编译错误
2. 不可变集合的copyOf()方法¶
List<String> original = new ArrayList<>();
original.add("A");
original.add("B");
// 创建不可变副本
List<String> copy = List.copyOf(original);
Java 11 (2018) - LTS¶
⭐⭐⭐⭐ 长期支持版本,广泛使用
1. 字符串增强¶
// isBlank() - 判断是否为空或只包含空白字符
" ".isBlank(); // true
"Hello".isBlank(); // false
// lines() - 分割为行的Stream
String multiline = "Line1\nLine2\nLine3";
multiline.lines().forEach(System.out::println);
// strip() / stripLeading() / stripTrailing() - 去除空白
" Hello ".strip(); // "Hello"
" Hello ".stripLeading(); // "Hello "
" Hello ".stripTrailing(); // " Hello"
// repeat() - 重复字符串
"Java ".repeat(3); // "Java Java Java "
2. 文件读写增强¶
// 读取文件为字符串
String content = Files.readString(Path.of("file.txt"));
// 写入字符串到文件
Files.writeString(Path.of("file.txt"), "Hello World");
3. HTTP Client API (标准)¶
// Java 11之前需要使用第三方库(如Apache HttpClient)
// Java 11+内置HTTP Client
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.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);
4. Lambda参数使用var¶
// Java 11之前
BiFunction<Integer, Integer, Integer> add =
(Integer a, Integer b) -> a + b;
// Java 11+: Lambda参数可以使用var
BiFunction<Integer, Integer, Integer> add2 =
(var a, var b) -> a + b;
// 使用场景:添加注解
BiFunction<Integer, Integer, Integer> add3 =
(@NonNull var a, @NonNull var b) -> a + b;
Java 12-16 (2019-2021)¶
Java 12: Switch表达式 (预览)¶
// 传统switch语句
String result;
switch (day) {
case MONDAY:
case FRIDAY:
result = "工作日";
break;
case SATURDAY:
case SUNDAY:
result = "周末";
break;
default:
result = "未知";
}
// Java 12+: Switch表达式
String result = switch (day) {
case MONDAY, FRIDAY -> "工作日";
case SATURDAY, SUNDAY -> "周末";
default -> "未知";
};
Java 13: 文本块 (Text Blocks) (预览)¶
// 传统多行字符串
String html = "<html>\n" +
" <body>\n" +
" <p>Hello</p>\n" +
" </body>\n" +
"</html>";
// Java 13+: 文本块
String html = """
<html>
<body>
<p>Hello</p>
</body>
</html>
""";
// JSON示例
String json = """
{
"name": "张三",
"age": 25,
"city": "北京"
}
""";
Java 14: Switch表达式 (正式)、Records (预览)¶
// Switch表达式正式版
var result = switch (day) {
case MONDAY, FRIDAY -> {
System.out.println("工作日");
yield "需要工作"; // yield返回值
}
case SATURDAY, SUNDAY -> "周末";
default -> "未知";
};
// Records (预览)
// 传统POJO
class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String name() { return name; }
public int age() { return age; }
@Override
public boolean equals(Object o) { /* ... */ }
@Override
public int hashCode() { /* ... */ }
@Override
public String toString() { /* ... */ }
}
// Java 14+: Record
record Person(String name, int age) {}
// 自动生成:构造器、getter、equals、hashCode、toString
Java 15: 文本块 (正式)、Sealed Classes (预览)¶
// Sealed Classes - 限制继承
public sealed class Shape
permits Circle, Rectangle, Triangle {
}
final class Circle extends Shape { }
final class Rectangle extends Shape { }
final class Triangle extends Shape { }
// 现在不能再继承Shape了
// class Square extends Shape { } // 编译错误!
Java 16: Records (正式)、Pattern Matching for instanceof (正式)¶
// 传统instanceof
if (obj instanceof String) {
String str = (String) obj;
System.out.println(str.length());
}
// Java 16+: Pattern Matching
if (obj instanceof String str) {
System.out.println(str.length()); // 直接使用str
}
Java 17 (2021) - LTS¶
⭐⭐⭐⭐ 长期支持版本,推荐生产使用
1. Sealed Classes (正式)¶
// 密封类:限制哪些类可以继承
public sealed class Vehicle
permits Car, Truck, Motorcycle {
private String brand;
public Vehicle(String brand) {
this.brand = brand;
}
}
// 子类必须是final、sealed或non-sealed
final class Car extends Vehicle {
public Car(String brand) {
super(brand);
}
}
sealed class Truck extends Vehicle
permits PickupTruck {
public Truck(String brand) {
super(brand);
}
}
non-sealed class Motorcycle extends Vehicle {
public Motorcycle(String brand) {
super(brand);
}
}
// Motorcycle是non-sealed,可以被任意继承
class SportBike extends Motorcycle {
public SportBike(String brand) {
super(brand);
}
}
2. Pattern Matching for switch (预览)¶
// 传统方式
static String formatter(Object obj) {
String formatted = "unknown";
if (obj instanceof Integer i) {
formatted = String.format("int %d", i);
} else if (obj instanceof Long l) {
formatted = String.format("long %d", l);
} else if (obj instanceof Double d) {
formatted = String.format("double %f", d);
} else if (obj instanceof String s) {
formatted = String.format("String %s", s);
}
return formatted;
}
// Java 17+: Pattern Matching for switch
static String formatter(Object obj) {
return switch (obj) {
case Integer i -> String.format("int %d", i);
case Long l -> String.format("long %d", l);
case Double d -> String.format("double %f", d);
case String s -> String.format("String %s", s);
default -> obj.toString();
};
}
3. 增强的伪随机数生成器¶
// Java 17+: 新的随机数API
RandomGenerator generator = RandomGenerator.of("L64X128MixRandom");
int randomInt = generator.nextInt();
double randomDouble = generator.nextDouble();
Java 18-20 (2022-2023)¶
Java 18: UTF-8默认字符集、简单Web服务器¶
Java 19: Virtual Threads (预览)、Record Patterns (预览)¶
// Virtual Threads (预览)
Thread.startVirtualThread(() -> {
System.out.println("虚拟线程运行中");
});
// Record Patterns (预览)
record Point(int x, int y) {}
static void printPoint(Object obj) {
if (obj instanceof Point(int x, int y)) {
System.out.println("x = " + x + ", y = " + y);
}
}
Java 20: Record Patterns (二次预览)、Pattern Matching for switch (四次预览)¶
Java 21 (2023) - LTS¶
⭐⭐⭐⭐⭐ 最新LTS版本,重大更新
1. Virtual Threads (正式) - 虚拟线程¶
/**
* 虚拟线程:轻量级线程,可以创建数百万个
* Virtual Threads: Lightweight threads
*/
// 传统线程
Thread thread = new Thread(() -> {
System.out.println("传统线程");
});
thread.start();
// Java 21+: 虚拟线程
Thread virtualThread = Thread.startVirtualThread(() -> {
System.out.println("虚拟线程");
});
// 使用Executor
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 1_000_000; i++) {
executor.submit(() -> {
Thread.sleep(Duration.ofSeconds(1));
return "Done";
});
}
} // executor自动等待所有任务完成
// 性能对比
// 传统线程:创建10,000个线程会消耗大量内存
// 虚拟线程:可以轻松创建1,000,000个虚拟线程
2. Sequenced Collections - 有序集合¶
// 新增的有序集合接口
interface SequencedCollection<E> extends Collection<E> {
SequencedCollection<E> reversed(); // 反转视图
void addFirst(E e); // 添加到开头
void addLast(E e); // 添加到末尾
E getFirst(); // 获取第一个元素
E getLast(); // 获取最后一个元素
E removeFirst(); // 移除第一个元素
E removeLast(); // 移除最后一个元素
}
// 使用示例
List<String> list = new ArrayList<>();
list.addFirst("A"); // 添加到开头
list.addLast("C"); // 添加到末尾
String first = list.getFirst(); // 获取第一个
String last = list.getLast(); // 获取最后一个
// 反转视图
List<String> reversed = list.reversed();
3. Record Patterns (正式)¶
record Point(int x, int y) {}
// Record Pattern Matching
static void printPoint(Object obj) {
if (obj instanceof Point(int x, int y)) {
System.out.println("Point: x=" + x + ", y=" + y);
}
}
// 嵌套Record Patterns
record Rectangle(Point topLeft, Point bottomRight) {}
static void printRectangle(Object obj) {
if (obj instanceof Rectangle(Point(int x1, int y1), Point(int x2, int y2))) {
System.out.println("Rectangle: (" + x1 + "," + y1 +
") to (" + x2 + "," + y2 + ")");
}
}
4. Pattern Matching for switch (正式)¶
// 完整的Pattern Matching for switch
static String testObject(Object obj) {
return switch (obj) {
case null -> "Null";
case Integer i when i > 0 -> "Positive Integer: " + i;
case Integer i when i < 0 -> "Negative Integer: " + i;
case Integer i -> "Zero";
case Long l -> "Long: " + l;
case Double d -> "Double: " + d;
case String s when s.length() > 5 -> "Long String: " + s;
case String s -> "Short String: " + s;
case Point(int x, int y) -> "Point: " + x + "," + y;
default -> "Unknown type";
};
}
5. String Templates (预览)¶
// 传统字符串拼接
String name = "张三";
int age = 25;
String message = "姓名: " + name + ", 年龄: " + age;
// Java 21+: String Templates (预览)
// String message = STR."姓名: \{name}, 年龄: \{age}";
版本选择建议¶
生产环境推荐¶
| 版本 | 推荐度 | 说明 |
|---|---|---|
| Java 8 | ⭐⭐⭐ | 稳定、生态完善,但即将EOL |
| Java 11 | ⭐⭐⭐⭐ | LTS,稳定可靠,广泛使用 |
| Java 17 | ⭐⭐⭐⭐⭐ | LTS,推荐新项目使用 |
| Java 21 | ⭐⭐⭐⭐ | 最新LTS,适合新项目,需测试 |
学习建议¶
- 基础学习:从Java 8开始,掌握Lambda、Stream、Optional
- 进阶学习:学习Java 11~17的新特性,了解Records、Sealed Classes
- 前沿技术:关注Java 21的Virtual Threads、Pattern Matching
- 实战应用:在项目中逐步应用新特性
面试高频问题¶
Q1: Java 8有哪些重要特性?⭐⭐⭐⭐⭐¶
答案: 1. Lambda表达式 2. Stream API 3. Optional类 4. 接口默认方法 5. 新的日期时间API (java.time) 6. 方法引用 7. CompletableFuture 8. Nashorn JavaScript引擎
Q2: Java 11相比Java 8有哪些改进?⭐⭐⭐⭐¶
答案: 1. HTTP Client API (标准化) 2. 字符串增强 (isBlank, lines, strip, repeat) 3. 文件读写增强 4. Lambda参数支持var 5. 移除JavaEE和CORBA模块 6. ZGC垃圾收集器 (实验性) 7. Epsilon垃圾收集器
Q3: Record和普通类有什么区别?⭐⭐⭐⭐¶
答案:
Record是不可变数据类,自动生成: - 私有final字段 - 构造器 - Getter方法 (不带get前缀) - equals()、hashCode()、toString()
区别: - Record不能继承其他类 (但可以实现接口) - Record的字段都是final - Record不能声明实例变量 - Record更简洁,减少样板代码
Q4: Sealed Classes的作用是什么?⭐⭐⭐⭐¶
答案:
Sealed Classes限制哪些类可以继承它,提供更严格的继承控制。
好处: 1. 明确类层次结构 2. 增强类型安全 3. 编译器可以做完整性检查 4. 配合Pattern Matching使用更强大
Q5: 虚拟线程有什么优势?⭐⭐⭐⭐⭐¶
答案:
优势: 1. 轻量级:可以创建数百万个虚拟线程 2. 低开销:内存占用小,上下文切换快 3. 简化并发编程:可以用同步代码风格编写异步逻辑 4. 提高吞吐量:特别适合I/O密集型应用
对比: - 传统线程:对应OS线程,创建/销毁开销大 - 虚拟线程:JVM管理,由Carrier线程调度
Q6: 应该选择哪个Java版本?⭐⭐⭐⭐¶
答案:
生产环境: - 保守:Java 11 (LTS,稳定) - 推荐:Java 17 (LTS,现代化) - 激进:Java 21 (最新LTS)
学习: - 必学:Java 8 (Lambda、Stream) - 推荐:Java 11-17 (Records、Sealed Classes) - 了解:Java 21 (Virtual Threads)
考虑因素: 1. 项目需求 2. 团队技术栈 3. 第三方库兼容性 4. 长期维护成本
总结 (Summary)¶
Java版本演进路线:
- Java 8 (2014):Lambda、Stream、Optional - 革命性更新
- Java 9 (2017):模块化、JShell
- Java 11 (2018):LTS,HTTP Client、字符串增强
- Java 17 (2021):LTS,Sealed Classes、Pattern Matching
- Java 21 (2023):LTS,Virtual Threads、Sequenced Collections
学习建议:
- 掌握Java 8:Lambda、Stream、Optional是基础
- 了解Java 11-17:Records、Sealed Classes、Pattern Matching
- 关注Java 21:Virtual Threads是未来趋势
- 实践应用:在项目中逐步应用新特性
上一篇: ← 04 - 函数式编程
返回目录: Java 语言基础导航 ←