Skip to content

JDK 8

JDK 8 的核心变化是把函数式编程能力引入 Java,同时补齐日期时间、异步编程和常用基础 API。它也是后续版本演进的基线。

Lambda 与函数式接口

Lambda 可以把行为作为参数传递。函数式接口只能有一个抽象方法,可以使用 @FunctionalInterface 让编译器进行校验。

java
@FunctionalInterface
interface Converter<F, T> {
    T convert(F value);
}

Converter<String, Integer> converter = Integer::valueOf;
int result = converter.convert("42");

常用函数式接口包括 Predicate<T>Function<T, R>Consumer<T>Supplier<T>UnaryOperator<T>BinaryOperator<T>

接口方法

接口可以声明 default 方法和 static 方法,在不破坏已有实现类的前提下演进 API。

java
interface Named {
    String name();

    default String displayName() {
        return name().toUpperCase();
    }

    static Named of(String name) {
        return () -> name;
    }
}

Stream API

Stream 用声明式流水线处理数据,分为中间操作和终止操作。Stream 本身不存储数据,也不能重复消费。

java
List<String> names = users.stream()
        .filter(User::isActive)
        .map(User::getName)
        .distinct()
        .sorted()
        .collect(Collectors.toList());

Stream.toList() 到 JDK 16 才加入,因此 JDK 8 必须使用 Collector。

并行流使用公共 ForkJoinPool,不应看到 parallelStream() 就默认使用;需要结合数据规模、任务性质和线程池干扰评估。

Date and Time API

java.time 替代线程不安全且语义混乱的 DateCalendarSimpleDateFormat

类型用途
InstantUTC 时间线上的时间点
LocalDate不带时区的日期
LocalDateTime不带时区的日期时间
ZonedDateTime带时区规则的日期时间
Duration基于秒和纳秒的时间量
Period基于年月日的日期量

CompletableFuture

CompletableFuture 支持异步任务编排、转换、组合和异常处理。

java
CompletableFuture<User> userFuture =
        CompletableFuture.supplyAsync(() -> userService.find(id), executor);

CompletableFuture<List<Order>> orderFuture =
        userFuture.thenApplyAsync(user -> orderService.findByUser(user.id()), executor);

生产环境应显式传入业务线程池,避免所有任务争用公共 ForkJoinPool

其他重要变化

特性说明
Optional表达可能缺失的返回值,不建议作为实体字段或方法参数滥用
方法与构造器引用Type::methodobject::methodType::new
重复注解使用 @Repeatable 在同一声明上重复应用注解
类型注解注解可以出现在类型使用位置,便于静态分析
Base64 APIjava.util.Base64 提供 Basic、URL、MIME 编解码
Map 增强computeIfAbsentmergeforEach 等默认方法
并发累加器LongAdderLongAccumulator 降低高竞争计数开销
元空间HotSpot 使用本地内存中的 Metaspace 取代永久代
Nashorn引入 JavaScript 引擎,后来在 JDK 15 中移除

架构与迁移关注

  • Lambda 捕获的局部变量必须是 final 或 effectively final。
  • Stream 的延迟执行和副作用会增加调试难度,业务流水线应保持无状态。
  • Optional.get() 可能抛异常,应优先使用 orElseThrowmapflatMap 等组合方法。
  • JDK 8 引入 Metaspace 后,类加载泄漏仍然存在,只是监控参数从永久代切换到了 Metaspace。