Java各个版本的新特性
Java各个版本的新特性
概述
Java自1995年发布以来,经历了多个重要版本的迭代。每个版本都引入了新的特性和改进,本文档总结了从Java 8到最新版本的主要新特性。
Java 8 (LTS) - 2014年3月
Lambda表达式
java
// 传统方式
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.sort(new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});
// Lambda表达式
names.sort((a, b) -> a.compareTo(b));
names.sort(String::compareTo); // 方法引用
// 传统方式
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.sort(new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});
// Lambda表达式
names.sort((a, b) -> a.compareTo(b));
names.sort(String::compareTo); // 方法引用
Stream API
java
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// 过滤和转换
List<String> result = names.stream()
.filter(name -> name.length() > 3)
.map(String::toUpperCase)
.collect(Collectors.toList());
// 聚合操作
Optional<String> longest = names.stream()
.max(Comparator.comparing(String::length));
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");
// 过滤和转换
List<String> result = names.stream()
.filter(name -> name.length() > 3)
.map(String::toUpperCase)
.collect(Collectors.toList());
// 聚合操作
Optional<String> longest = names.stream()
.max(Comparator.comparing(String::length));
接口默认方法
java
public interface Vehicle {
void start();
// 默认方法
default void stop() {
System.out.println("Vehicle stopped");
}
// 静态方法
static void checkEngine() {
System.out.println("Engine checked");
}
}
public interface Vehicle {
void start();
// 默认方法
default void stop() {
System.out.println("Vehicle stopped");
}
// 静态方法
static void checkEngine() {
System.out.println("Engine checked");
}
}
Optional类
java
Optional<String> optional = Optional.ofNullable(getString());
// 避免空指针异常
optional.ifPresent(System.out::println);
// 提供默认值
String result = optional.orElse("default");
// 链式调用
String processed = optional
.filter(s -> s.length() > 5)
.map(String::toUpperCase)
.orElse("SHORT");
Optional<String> optional = Optional.ofNullable(getString());
// 避免空指针异常
optional.ifPresent(System.out::println);
// 提供默认值
String result = optional.orElse("default");
// 链式调用
String processed = optional
.filter(s -> s.length() > 5)
.map(String::toUpperCase)
.orElse("SHORT");
新的日期时间API
java
// LocalDate, LocalTime, LocalDateTime
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime dateTime = LocalDateTime.now();
// 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = dateTime.format(formatter);
// 计算
LocalDate nextWeek = date.plusWeeks(1);
long daysBetween = ChronoUnit.DAYS.between(date, nextWeek);
// LocalDate, LocalTime, LocalDateTime
LocalDate date = LocalDate.now();
LocalTime time = LocalTime.now();
LocalDateTime dateTime = LocalDateTime.now();
// 格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = dateTime.format(formatter);
// 计算
LocalDate nextWeek = date.plusWeeks(1);
long daysBetween = ChronoUnit.DAYS.between(date, nextWeek);
Java 9 - 2017年9月
模块系统(Project Jigsaw)
java
// module-info.java
module com.example.myapp {
requires java.base;
requires java.logging;
exports com.example.myapp.api;
}
// module-info.java
module com.example.myapp {
requires java.base;
requires java.logging;
exports com.example.myapp.api;
}
JShell(交互式编程环境)
bash
$ jshell
jshell> int x = 10
x ==> 10
jshell> System.out.println("Hello " + x)
Hello 10
$ jshell
jshell> int x = 10
x ==> 10
jshell> System.out.println("Hello " + x)
Hello 10
集合工厂方法
java
// 不可变集合
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);
// 不可变集合
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);
接口私有方法
java
public interface MyInterface {
default void method1() {
commonMethod();
}
default void method2() {
commonMethod();
}
// 私有方法
private void commonMethod() {
System.out.println("Common logic");
}
}
public interface MyInterface {
default void method1() {
commonMethod();
}
default void method2() {
commonMethod();
}
// 私有方法
private void commonMethod() {
System.out.println("Common logic");
}
}
Java 10 - 2018年3月
局部变量类型推断(var)
java
// 类型推断
var list = new ArrayList<String>();
var map = new HashMap<String, Integer>();
// 在循环中使用
for (var item : list) {
System.out.println(item);
}
// 类型推断
var list = new ArrayList<String>();
var map = new HashMap<String, Integer>();
// 在循环中使用
for (var item : list) {
System.out.println(item);
}
应用程序类数据共享(AppCDS)
提高应用启动时间和减少内存占用。
Java 11 (LTS) - 2018年9月
字符串新方法
java
String str = " Hello World ";
// 判断是否为空白
boolean isBlank = str.isBlank();
// 去除首尾空白
String stripped = str.strip();
// 重复字符串
String repeated = "Java".repeat(3); // "JavaJavaJava"
// 按行分割
Stream<String> lines = "Line1\nLine2\nLine3".lines();
String str = " Hello World ";
// 判断是否为空白
boolean isBlank = str.isBlank();
// 去除首尾空白
String stripped = str.strip();
// 重复字符串
String repeated = "Java".repeat(3); // "JavaJavaJava"
// 按行分割
Stream<String> lines = "Line1\nLine2\nLine3".lines();
HTTP客户端API
java
HttpClient client = HttpClient.newHttpClient();
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());
HttpClient client = HttpClient.newHttpClient();
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());
运行单文件源代码
bash
# 直接运行Java源文件,无需编译
java HelloWorld.java
# 直接运行Java源文件,无需编译
java HelloWorld.java
Java 12 - 2019年3月
Switch表达式(预览)
java
// 传统switch
String result;
switch (day) {
case MONDAY:
case FRIDAY:
result = "Working day";
break;
case SATURDAY:
case SUNDAY:
result = "Weekend";
break;
default:
result = "Unknown";
}
// 新的switch表达式
String result = switch (day) {
case MONDAY, FRIDAY -> "Working day";
case SATURDAY, SUNDAY -> "Weekend";
default -> "Unknown";
};
// 传统switch
String result;
switch (day) {
case MONDAY:
case FRIDAY:
result = "Working day";
break;
case SATURDAY:
case SUNDAY:
result = "Weekend";
break;
default:
result = "Unknown";
}
// 新的switch表达式
String result = switch (day) {
case MONDAY, FRIDAY -> "Working day";
case SATURDAY, SUNDAY -> "Weekend";
default -> "Unknown";
};
Java 13 - 2019年9月
文本块(预览)
java
// 传统字符串
String html = "<html>\n" +
" <body>\n" +
" <p>Hello World</p>\n" +
" </body>\n" +
"</html>";
// 文本块
String html = """
<html>
<body>
<p>Hello World</p>
</body>
</html>
""";
// 传统字符串
String html = "<html>\n" +
" <body>\n" +
" <p>Hello World</p>\n" +
" </body>\n" +
"</html>";
// 文本块
String html = """
<html>
<body>
<p>Hello World</p>
</body>
</html>
""";
Java 14 - 2020年3月
Switch表达式(正式)
Switch表达式从预览特性转为正式特性。
记录类型(预览)
java
// 传统类
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
// getter, equals, hashCode, toString...
}
// 记录类型
public record Point(int x, int y) {}
// 传统类
public class Point {
private final int x;
private final int y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
// getter, equals, hashCode, toString...
}
// 记录类型
public record Point(int x, int y) {}
instanceof模式匹配(预览)
java
// 传统方式
if (obj instanceof String) {
String str = (String) obj;
System.out.println(str.length());
}
// 模式匹配
if (obj instanceof String str) {
System.out.println(str.length());
}
// 传统方式
if (obj instanceof String) {
String str = (String) obj;
System.out.println(str.length());
}
// 模式匹配
if (obj instanceof String str) {
System.out.println(str.length());
}
Java 15 - 2020年9月
文本块(正式)
文本块从预览特性转为正式特性。
密封类(预览)
java
public sealed class Shape
permits Circle, Rectangle, Triangle {
}
public final class Circle extends Shape {}
public final class Rectangle extends Shape {}
public final class Triangle extends Shape {}
public sealed class Shape
permits Circle, Rectangle, Triangle {
}
public final class Circle extends Shape {}
public final class Rectangle extends Shape {}
public final class Triangle extends Shape {}
Java 16 - 2021年3月
记录类型(正式)
记录类型从预览特性转为正式特性。
instanceof模式匹配(正式)
instanceof模式匹配从预览特性转为正式特性。
Stream.toList()
java
List<String> list = stream
.filter(s -> s.length() > 3)
.toList(); // 新方法,返回不可变列表
List<String> list = stream
.filter(s -> s.length() > 3)
.toList(); // 新方法,返回不可变列表
Java 17 (LTS) - 2021年9月
密封类(正式)
密封类从预览特性转为正式特性。
随机数生成器增强
java
RandomGenerator generator = RandomGenerator.of("Xoshiro256PlusPlus");
int randomInt = generator.nextInt(1, 100);
RandomGenerator generator = RandomGenerator.of("Xoshiro256PlusPlus");
int randomInt = generator.nextInt(1, 100);
移除实验性AOT和JIT编译器
移除了实验性的AOT编译器和Graal JIT编译器。
Java 18 - 2022年3月
UTF-8默认字符集
UTF-8成为标准Java API的默认字符集。
简单Web服务器
bash
# 启动简单的文件服务器
jwebserver -p 8080 -d /path/to/directory
# 启动简单的文件服务器
jwebserver -p 8080 -d /path/to/directory
代码片段在Javadoc中
java
/**
* 示例方法
* {@snippet :
* var list = List.of("a", "b", "c");
* list.forEach(System.out::println);
* }
*/
public void example() {}
/**
* 示例方法
* {@snippet :
* var list = List.of("a", "b", "c");
* list.forEach(System.out::println);
* }
*/
public void example() {}
Java 19 - 2022年9月
虚拟线程(预览)
java
// 创建虚拟线程
Thread.startVirtualThread(() -> {
System.out.println("Virtual thread: " + Thread.currentThread());
});
// 使用ExecutorService
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> {
// 任务代码
});
}
// 创建虚拟线程
Thread.startVirtualThread(() -> {
System.out.println("Virtual thread: " + Thread.currentThread());
});
// 使用ExecutorService
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> {
// 任务代码
});
}
结构化并发(孵化)
java
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<String> user = scope.fork(() -> findUser());
Future<String> order = scope.fork(() -> findOrder());
scope.join(); // 等待所有任务完成
scope.throwIfFailed(); // 如果有失败则抛出异常
// 使用结果
return new Response(user.resultNow(), order.resultNow());
}
try (var scope = new StructuredTaskScope.ShutdownOnFailure()) {
Future<String> user = scope.fork(() -> findUser());
Future<String> order = scope.fork(() -> findOrder());
scope.join(); // 等待所有任务完成
scope.throwIfFailed(); // 如果有失败则抛出异常
// 使用结果
return new Response(user.resultNow(), order.resultNow());
}
Java 20 - 2023年3月
作用域值(孵化)
java
public class UserContext {
public static final ScopedValue<String> USER_ID = ScopedValue.newInstance();
}
// 绑定值
ScopedValue.where(UserContext.USER_ID, "user123")
.run(() -> {
// 在这个作用域内可以访问USER_ID
String userId = UserContext.USER_ID.get();
});
public class UserContext {
public static final ScopedValue<String> USER_ID = ScopedValue.newInstance();
}
// 绑定值
ScopedValue.where(UserContext.USER_ID, "user123")
.run(() -> {
// 在这个作用域内可以访问USER_ID
String userId = UserContext.USER_ID.get();
});
Java 21 (LTS) - 2023年9月
虚拟线程(正式)
虚拟线程从预览特性转为正式特性。
字符串模板(预览)
java
String name = "World";
int value = 42;
// 字符串模板
String message = STR."Hello \{name}, value is \{value}";
String name = "World";
int value = 42;
// 字符串模板
String message = STR."Hello \{name}, value is \{value}";
序列集合
java
// 新的集合接口,提供统一的首尾访问方法
SequencedCollection<String> list = new ArrayList<>();
list.addFirst("first");
list.addLast("last");
String first = list.getFirst();
String last = list.getLast();
// 新的集合接口,提供统一的首尾访问方法
SequencedCollection<String> list = new ArrayList<>();
list.addFirst("first");
list.addLast("last");
String first = list.getFirst();
String last = list.getLast();
版本选择建议
LTS版本推荐
- Java 8:仍被广泛使用,但逐渐过时
- Java 11:当前主流LTS版本,推荐用于生产环境
- Java 17:最新LTS版本,推荐新项目使用
- Java 21:最新LTS版本,包含最新特性
升级考虑因素
- 兼容性:检查第三方库和框架的支持情况
- 性能:新版本通常有性能改进
- 安全性:新版本包含安全修复
- 特性需求:是否需要新版本的特定特性
- 维护成本:团队学习和迁移成本
总结
Java持续演进,每个版本都带来新的特性和改进。对于生产环境,建议使用LTS版本以获得长期支持。同时,了解新特性有助于编写更简洁、高效的代码。选择Java版本时应综合考虑项目需求、团队能力和生态系统支持情况。