cd ..
2025-11-2812 min40 views

代码的艺术:从 JDK 8 的函数式狂潮到 JDK 17 的现代优雅

#Java#Jdk8#StreamApi#LambdaExpressions#OptionalClass
AI Summary
每分钟最多 5 次
  • JDK 8 引入了 Lambda 表达式、Stream API 和 Optional 类,这些特性极大地增强了 Java 的函数式编程能力,简化了代码编写并提高了处理集合数据的效率。
  • JDK 9 推出了模块化系统(JPMS)和 JShell,前者通过更好的依赖管理和封装提升了大型应用的性能与安全性;后者提供了一个交互式的 Java 环境,便于快速测试代码片段。
  • JDK 10 引入局部变量类型推断 (var),使得代码更加简洁的同时保持了类型安全。
  • JDK 11 包含了新的 HTTP Client API 和实验性的 ZGC 垃圾收集器,提供了更现代且高效的网络请求处理方式及内存管理方案。
  • 从 JDK 12 到 JDK 17,增加了 Switch 表达式、文本块、Record 类型以及 Sealed Classes 等功能,进一步丰富了语言特性,使 Java 编程更加灵活高效。特别是 JDK 17 作为一个 LTS 版本,整合了之前版本的所有改进,为开发者提供了一个稳定可靠的开发平台。

为了便于阅读,本文将分为以下几个部分:

  • JDK 8:流(Stream)、函数式接口、默认方法、Optional 类
  • JDK 9:模块化系统(Jigsaw)、JShell
  • JDK 10:局部变量类型推断(var)
  • JDK 11:HTTP Client、ZGC 垃圾收集器(实验性)
  • JDK 12 & 13:Switch 表达式、Text Blocks(文本块)
  • JDK 14 & 15:Record 类型、Sealed Classes(密封类)
  • JDK 16:Record、Sealed Classes(最终版本)
  • JDK 17:LTS 版本,主要特性为前面版本的累积和稳定

JDK 8:Java 的“文艺复兴”

JDK 8 是 Java 历史上最重要的一次版本更新,引入了大量现代编程范式,彻底改变了 Java 的编写方式。

1. Lambda 表达式与函数式接口

Lambda 表达式让 Java 能够以更简洁的语法实现匿名函数,核心是函数式接口。一个函数式接口是指只有一个抽象方法的接口,例如 RunnableCallable

官方文档: Lambda Expressions

代码示例:

Java

 // 传统写法:匿名内部类
 new Thread(new Runnable() {
     @Override
     public void run() {
         System.out.println("Hello from a thread!");
     }
 }).start();
 
 // JDK 8 Lambda 写法
 new Thread(() -> System.out.println("Hello from a lambda thread!")).start();

2. Stream API

Stream API 提供了一种全新的方式来处理集合数据,它支持声明式编程,让你能够像 SQL 一样对集合进行“查询”。Stream 本身是不可变的,并且是懒加载的。

官方文档: Stream API

代码示例:

Java

 List<String> names = Arrays.asList("Tom", "Jerry", "Spike", "Tom");
 
 // 筛选出以 "T" 开头的,转换成大写,去重,并打印
 names.stream()
      .filter(name -> name.startsWith("T")) // 筛选
      .map(String::toUpperCase)              // 转换
      .distinct()                            // 去重
      .forEach(System.out::println);         // 遍历打印

3. Optional 类

Optional<T> 是一个容器对象,可以包含或不包含一个非 null 值。它的主要目的是解决空指针异常(NullPointerException,鼓励你以更函数式的方式来处理可能为空的值。

官方文档: Optional Class

代码示例:

Java

 String name = "John";
 String nullName = null;
 
 Optional<String> optionalName = Optional.ofNullable(name);
 Optional<String> optionalNullName = Optional.ofNullable(nullName);
 
 // 使用 orElse,如果值不存在,则提供一个默认值
 String result1 = optionalName.orElse("Default"); // "John"
 String result2 = optionalNullName.orElse("Default"); // "Default"
 
 // 使用 ifPresent,当值存在时执行一个操作
 optionalName.ifPresent(n -> System.out.println("Hello, " + n));

JDK 9:模块化与 JShell

JDK 9 的核心是 Project Jigsaw,旨在解决大型应用中依赖管理混乱的问题,并提高性能。

1. 模块化系统(JPMS)

Java Platform Module System (JPMS) 允许你将代码组织成独立的模块。每个模块都有一个 module-info.java 文件,明确声明它依赖哪些模块,以及它对外暴露哪些包。

官方文档: Java Platform Module System

2. JShell

JShell 是一个交互式的 Java REPL (Read-Eval-Print Loop) 工具。你可以直接在命令行中输入 Java 代码片段并立即执行,无需编写完整的 main 方法。这对于学习 Java 语法或测试代码片段非常有用。

官方文档: JShell Guide

代码示例 (在命令行中):

Bash

 > jshell
 |  Welcome to JShell -- Version 9
 |  For an introduction type: /help intro
 
 jshell> int sum = 10 + 20;
 sum ==> 30
 
 jshell> System.out.println("Hello, JShell!");
 Hello, JShell!

JDK 10:局部变量类型推断(var

var 关键字允许你在声明局部变量时,让编译器根据初始化值自动推断其类型。这能让代码更简洁,但要注意不能用于方法参数、返回值或成员变量。

官方文档: JEP 286: Local-Variable Type Inference

代码示例:

Java

 // JDK 9 及之前
 Map<String, List<String>> myMap = new HashMap<String, List<String>>();
 
 // JDK 10 以后
 var myMap = new HashMap<String, List<String>>();

JDK 11:新 HTTP Client 和 ZGC

JDK 11 是一个 LTS (Long-Term Support) 版本,带来了生产就绪的 HTTP Client 和实验性的 ZGC

1. HTTP Client

JDK 11 中正式引入了新的 java.net.http.HttpClient,它提供了更现代、更易用的 API 来处理 HTTP 请求,支持同步和异步调用。

官方文档: HTTP Client

代码示例:

Java

 HttpClient client = HttpClient.newHttpClient();
 HttpRequest request = HttpRequest.newBuilder()
     .uri(URI.create("https://httpbin.org/get"))
     .GET() // 或 .POST(...)
     .build();
 
 // 同步发送请求
 HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
 System.out.println(response.body());

JDK 12 & 13:Switch 表达式与文本块

1. Switch 表达式

Switch 表达式允许 switch 语句作为表达式使用,并可以直接返回值,消除了传统 switch 中的 break 语句,避免了“穿透”问题。

官方文档: JEP 361: Switch Expressions (Standard)

代码示例:

Java

 // JDK 13 以后
 String day = "MONDAY";
 String result = switch (day) {
     case "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY" -> "Workday";
     case "SATURDAY", "SUNDAY" -> "Weekend";
     default -> throw new IllegalArgumentException("Invalid day: " + day);
 };
 System.out.println(result);

2. Text Blocks(文本块)

文本块提供了多行字符串的支持,使用三个双引号 """ 包围,无需手动转义换行符和引号,极大地简化了多行字符串(如 JSON、SQL)的编写。

官方文档: JEP 378: Text Blocks (Standard)

代码示例:

Java

 // 传统多行字符串
 String jsonOld = "{n" +
                  "  "name": "John",n" +
                  "  "age": 30n" +
                  "}";
 
 // 文本块
 String jsonNew = """
                  {
                    "name": "John",
                    "age": 30
                  }
                  """;
 System.out.println(jsonNew);

JDK 14 & 15:Record 与 Sealed Classes

1. Record(记录)

Record 是一种特殊的类,用于创建不可变的数据载体。它自动生成构造函数、访问器、equals()hashCode()toString() 方法,省去了大量样板代码。

官方文档: JEP 395: Records (Standard)

代码示例:

Java

// 传统数据类

public final 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…

}

// Record 写法

public record Point(int x, int y) {}

// 使用

Point p1 = new Point(10, 20);

System.out.println(p1.x()); // 访问器自动生成

System.out.println(p1);     // toString() 自动生成

2. Sealed Classes(密封类)

Sealed Classes 允许你限制哪些类可以继承一个类或实现一个接口。你使用 sealed 关键字声明一个类,并用 permits 关键字指定允许继承的子类。这为面向对象设计提供了更精细的控制。

官方文档: JEP 409: Sealed Classes (Standard)

代码示例:

Java

 // Shape 是一个密封接口,只允许 Circle 和 Square 实现
 public sealed interface Shape permits Circle, Square {}
 
 final class Circle implements Shape {}
 final class Square implements Shape {}
 
 // Polygon 不能实现 Shape,编译器会报错
 // class Polygon implements Shape {}

JDK 16 & 17:最终定型与 LTS

JDK 16 将 Record 和 Sealed Classes 这两个特性最终定型,使其可以用于生产环境。

JDK 17 作为最新的 LTS 版本,将上述所有新特性(如 Record、Sealed Classes、Text Blocks 等)整合并稳定下来。对于企业级应用来说,JDK 17 是一个非常推荐的升级目标,因为它在性能、稳定性和功能上都达到了一个新的高度。

希望这篇文章能帮助你快速了解 JDK 8 到 JDK 17 的演进过程。这些新特性大大提高了 Java 的开发效率和代码质量,值得你在项目中积极尝试。

/** Comments(0)*/

Loading comments...