Java 语言在过去十年中经历了革命性的变化,从 Java 8 的函数式编程到 Java 21 的虚拟线程,每个版本都带来了提升开发效率和性能的重大特性。本文将以详实的代码示例和直观的图解,带你系统掌握这些新特性的核心用法与适用场景。
Java 8 是史上最重大的版本,引入了函数式编程范式,彻底改变了 Java 代码的编写方式。
Lambda 表达式
告别冗长的匿名内部类,用简洁语法实现函数式编程:
// 传统匿名类
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("点击");
}
});
// Lambda 表达式
button.addActionListener(e -> System.out.println("点击"));方法引用
进一步简化 Lambda 表达式:
List<String> names = Arrays.asList("A", "B");
names.forEach(System.out::println); // 等价于 s -> System.out.println(s)函数式接口
@FunctionalInterface 注解确保接口只有一个抽象方法,作为 Lambda 的类型:
@FunctionalInterface
public interface Calculator {
double calculate(double a, double b);
}
// 使用
Calculator add = (a, b) -> a + b;Stream API
声明式处理集合数据,支持链式操作:
List<String> result = words.stream()
.filter(word -> word.length() > 5)
.map(String::toUpperCase)
.collect(Collectors.toList());
Optional 类
优雅处理空值,避免 NullPointerException:
Optional<String> name = Optional.ofNullable(getName());
String result = name.orElse("默认值");新的日期时间 API
解决旧 Date 类的线程安全和设计缺陷:
LocalDate today = LocalDate.now();
LocalDateTime time = LocalDateTime.of(2024, 1, 1, 12, 0);接口默认方法
允许接口提供默认实现,支持向后兼容:
public interface Drawable {
void draw();
default void drawWithBorder() {
System.out.println("绘制边框");
draw();
}
}模块系统
通过 module-info.java 定义模块依赖和封装:
module my.module {
requires java.base;
exports com.example.api;
}JShell 交互工具
REPL 环境快速测试代码片段:
jshell> 2 + 2
$1 ==> 4集合工厂方法
快速创建不可变集合:
List<String> list = List.of("A", "B");
Set<Integer> set = Set.of(1, 2);
Map<String, Integer> map = Map.of("key", 1);接口私有方法
在接口内复用代码:
public interface Transformer {
default void process(String input) {
validate(input);
// ...
}
private void validate(String input) {
if (input == null) throw new IllegalArgumentException();
}
}var 关键字
局部变量类型推断,保持代码简洁:
var list = new ArrayList<String>(); // 推断为 ArrayList<String>
var stream = list.stream(); // 推断为 Stream<String>HTTP 客户端 API
标准化 HTTP/2 客户端,支持同步/异步请求:
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());String 类新方法
增强字符串处理:
" ".isBlank(); // true
"abc".repeat(3); // "abcabcabc"
"line1
line2".lines().count(); // 2Files 类新方法
简化文件读写:
Files.writeString(Path.of("file.txt"), "内容");
String content = Files.readString(Path.of("file.txt"));Optional 新增 isEmpty()
补充空值检查:
Optional<String> opt = Optional.empty();
if (opt.isEmpty()) {
System.out.println("为空");
}引入 Switch 表达式、文本块等预览特性,为后续版本正式化做准备。
Switch 表达式
箭头语法、多标签合并、返回值:
String dayType = switch (day) {
case MONDAY, FRIDAY -> "工作日";
case SATURDAY, SUNDAY -> "周末";
default -> "未知";
};有用的空指针异常
优化错误信息,指出 null 具体位置。
文本块
多行字符串处理:
String json = """
{
"name": "Java",
"version": 15
}
""";Hidden 类
为框架优化动态类生成性能(如 Lambda 表达式),开发者无需直接使用。
Records
简化数据类定义:
public record Person(String name, int age) {}
Person person = new Person("Alice", 30);
String name = person.name(); // 自动 getterinstanceof 模式匹配
直接声明类型变量:
if (obj instanceof String s) {
System.out.println(s.length());
}Stream 新增 toList()
简化收集操作:
List<String> list = stream.filter(...).toList();Sealed 密封类
准确控制继承关系:
public sealed class Shape permits Circle, Rectangle {
// ...
}
public final class Circle extends Shape { /*...*/ }新的随机数生成器 API
更优算法选择:
RandomGenerator generator = RandomGenerator.of("L32X64MixRandom");
int number = generator.nextInt(100);简单 Web 服务器
开发测试用文件服务器:
jwebserver -p 8080 -d /path/to/filesUTF-8 默认字符集
确保跨平台一致性。
为 Java 21 的虚拟线程等特性做预备。
Virtual Threads 虚拟线程
轻量级线程,支持百万级并发:
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> {
String result = httpClient.get("https://example.com");
System.out.println(result);
});
}
Switch 模式匹配
直接匹配类型:
return switch (obj) {
case String s -> "字符串: " + s;
case Integer i -> "数字: " + i;
default -> "未知";
};Record 模式
解构 Record 对象:
if (person instanceof Person(String name, int age)) {
System.out.println(name + " is " + age + " years old");
}有序集合方法
新增 getFirst(), removeLast() 等方法。
分代 ZGC
垃圾回收器优化,区分年轻代和老年代提升效率。
外部函数和内存 API
标准化本地代码调用(替代 JNI):
// 示例:调用 C 函数
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
FunctionDescriptor desc = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT);
MethodHandle sqrt = linker.downcallHandle(stdlib.lookup("sqrt").get(), desc);
int result = (int) sqrt.invoke(25);未命名变量和模式
用 _ 忽略未使用变量:
try {
process();
} catch (IOException _) {
System.out.println("出错");
}分代 ZGC 成为默认垃圾回收器,进一步提升内存管理性能。
类文件 API
动态生成/修改字节码:
ClassFile cf = ClassFile.of();
byte[] bytes = cf.build(ClassDesc.of("Demo"), cb -> {
cb.withMethod("main", MethodTypeDesc.of(CD_void, CD_String.arrayType()), ACC_PUBLIC | ACC_STATIC, mb -> {
mb.withCode(codeb -> {
codeb.getstatic(CD_System, "out", CD_PrintStream);
codeb.ldc("Hello");
codeb.invokevirtual(CD_PrintStream, "println", MethodTypeDesc.of(CD_void, CD_String));
codeb.return_();
});
});
});Stream Gatherers
扩展 Stream API,支持复杂聚合(如滑动窗口):
List<Double> averages = prices.stream()
.gather(Gatherers.windowSliding(3))
.map(window -> window.stream().mapToDouble(Double::doubleValue).average().orElse(0.0))
.toList();
Java 的持续演进让开发者能编写更简洁、高效且安全的代码。提议结合实际项目需求,逐步引入新特性,提升开发体验和应用性