【工作记录】JDK8到JDK21都更新了哪些新特性

2024-04-03 18:36

本文主要是介绍【工作记录】JDK8到JDK21都更新了哪些新特性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在软件开发的世界里,Java作为一门久经沙场且持续焕发活力的编程语言,其每一次重大版本更新都承载着开发者们的热切期待。从JDK 8到JDK 21,这是一段跨越近十年的技术革新之旅,期间引入的一系列关键新特性不仅提升了开发效率,优化了性能,还顺应了现代软件工程的潮流,诸如函数式编程、模块化设计、安全性增强以及对云原生环境的更好支持等。本篇文章将带领读者一同回顾这段历程,聚焦JDK 8至JDK 21之间每个版本的核心亮点,揭示这些特性如何重塑Java生态,助力开发者们构建更为高效、简洁、安全的应用程序。


关键版本介绍

  • JDK 8,作为Java历史上的一个重要里程碑,带来了深远影响。它的革新之处在于广泛引入了lambda表达式、函数式接口、Stream API等,实现了对函数式编程范式的有力支持,极大地简化了集合处理逻辑,并提高了代码可读性。同时,接口中允许定义默认方法和静态方法,打破了以往接口只能声明抽象方法的传统,促进了API设计的灵活性。此外,全新的Date-Time API和Optional类则为处理时间和潜在空值提供了更为清晰、一致的工具。

  • JDK 9标志着Java平台的模块化时代的开启,通过Project Jigsaw项目实现了JDK自身的模块化结构,使得应用可以按需打包和加载模块,降低了应用的启动时间和内存占用,增强了封装性和安全性。此版本还引入了List、Set、Map的工厂方法,如List.of(),方便创建不可变集合;JShell作为交互式编程工具,加速了原型开发与学习过程;Optional类的改进进一步完善了函数式编程体验;而多版本兼容的JAR包格式及新的Javadoc生成工具,均为开发者工作流带来了便利。

  • 后续版本如JDK 10至JDK 15,每一个迭代都在前一版本的基础上稳步前行,引入了诸如局部变量类型推断、垃圾回收器改进、ZGC实验性并发标记清除收集器、动态类文件常量、文本块(Text Blocks)、密封类与接口(Sealed Classes and Interfaces)等特性,旨在提升编译时类型安全性、运行时性能以及代码编写舒适度。例如,JDK 11的String类新增了一系列实用方法,如isBlank()strip()等,以简化字符串操作;而JDK 12至JDK 15则陆续推出了Switch表达式、模式匹配预览、Records类型等语言层面的增强,持续降低冗余代码并提高表达力。

  • JDK 16至JDK 21,随着Java的发展步入稳定快速发布的节奏,每个半年发布周期均带来了一批重要功能和优化。其中包括但不限于:JEP 380(Vector API),提供硬件向量计算支持;JEP 398(Foreign-Memory Access API),便于安全地直接访问外部内存;JEP 391(Strongly Encapsulate JDK Internals by Default),强化了JDK内部组件的封装;以及针对容器化、微服务场景的诸多改进,如JFR事件流(JEP 382)、隐藏类(JEP 371)等。这些特性无不体现着Java对于现代开发需求的敏锐响应和持续进化。


关键版本特性使用示例

JDK8-lambda表达式

// Before JDK 8:
Collections.sort(names, new Comparator<String>() {@Overridepublic int compare(String a, String b) {return a.compareTo(b);}
});// With JDK 8 Lambda expression:
Collections.sort(names, (a, b) -> a.compareTo(b));

JDK8-stream API

// Filter a list and sum all even numbers
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);long sumOfEvens = numbers.stream().filter(n -> n % 2 == 0).mapToInt(Integer::intValue).sum();System.out.println(sumOfEvens); // Output: 12

JDK8-Optional

// Avoiding null pointer exceptions when dealing with optional values
Optional<String> optionalName = Optional.ofNullable(getUser().getName());String greeting = optionalName.orElse("Guest");
System.out.println("Hello, " + greeting + "!");// Or chaining methods with Optional
optionalName.ifPresent(name -> System.out.println("Found name: " + name));

JDK11-本地变量类型推断

/ Before JDK 11:
List<String> namesList = new ArrayList<>();// With JDK 11 var:
var namesList = new ArrayList<>();

JDK11-httpClient

import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://example.com")).build();HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());System.out.println(response.statusCode());
System.out.println(response.body());

JDK17-密封类

JDK 17 中引入的密封类(Sealed Classes)是一种新的类设计机制,它允许控制类的继承层次结构,限制谁能成为其子类。密封类有助于实现更好的模块化、增加编译时类型检查、提升安全性,并有助于减少错误的继承关系。以下是几种典型的使用场景:

场景一:有限的枚举替代
当需要表示一组相关的但数量有限且已知的具体类型时,密封类可以作为传统枚举类型的有力补充。虽然枚举适用于状态固定的实例集合,但它们往往缺乏灵活性,不能携带额外的属性或行为。密封类则允许定义具有不同状态和行为的子类,同时保持类型系统的封闭性。

public sealed interface PaymentMethod permits CreditCardPayment, BankTransfer, CashOnDelivery {String getPaymentDescription();
}public final class CreditCardPayment implements PaymentMethod {private final String cardNumber;// ... constructors, getters, setters, etc.@Overridepublic String getPaymentDescription() {return "Credit Card (" + cardNumber + ")";}
}public final class BankTransfer implements PaymentMethod {private final String accountNumber;// ... constructors, getters, setters, etc.@Overridepublic String getPaymentDescription() {return "Bank Transfer (" + accountNumber + ")";}
}public final class CashOnDelivery implements PaymentMethod {// No additional fields needed for this payment method@Overridepublic String getPaymentDescription() {return "Cash on Delivery";}
}

场景二:领域建模中的受限扩展
在领域驱动设计(DDD)中,密封类可用于精确控制业务实体或值对象的扩展。例如,一个电商系统可能只允许特定类型的优惠券策略,而防止意外或恶意扩展出不符合业务规则的策略类型。

public sealed abstract class CouponStrategy permits PercentageDiscount, FixedAmountDiscount, BundleDiscount {public abstract BigDecimal applyDiscount(Order order);
}public final class PercentageDiscount extends CouponStrategy {private final BigDecimal percentage;public PercentageDiscount(BigDecimal percentage) {this.percentage = percentage;}@Overridepublic BigDecimal applyDiscount(Order order) {// Apply percentage-based discount logic}
}// Other concrete coupon strategies follow the same pattern...public class OrderService {public void applyCoupon(Order order, CouponStrategy strategy) {// ...BigDecimal discount = strategy.applyDiscount(order);// ...}
}

场景三:API设计中的类型安全
在对外提供的API中,密封类可以确保只有指定的类型能够参与到特定的逻辑流程中,从而提高类型安全性。例如,一个图形渲染库可能只允许特定类型的形状参与渲染,避免用户误传入不支持的形状类型。

public sealed interface RenderableShape permits CircleRenderable, RectangleRenderable, TriangleRenderable {void render(GraphicsContext context);
}public final class CircleRenderable implements RenderableShape {// ...@Overridepublic void render(GraphicsContext context) {// Render circle logic}
}// Other renderable shapes...public class Renderer {public void drawScene(List<RenderableShape> shapes, GraphicsContext context) {for (RenderableShape shape : shapes) {shape.render(context);}}
}

场景四:编译时元编程与模式匹配
结合Java 17中的模式匹配(Pattern Matching for instanceof),密封类可以在编译时进行更精细的类型检查和转换,简化代码并消除运行时类型错误。例如,一个解析JSON响应的任务可以根据不同的响应类型采取不同的处理逻辑。

public sealed interface ApiResponse permits SuccessResponse, ErrorResponse {// Common methods or properties...
}public final class SuccessResponse implements ApiResponse {private final String data;// Constructor, getters, etc.
}public final class ErrorResponse implements ApiResponse {private final int errorCode;private final String errorMessage;// Constructor, getters, etc.
}public void handleApiResponse(ApiResponse response) {switch (response) {case SuccessResponse success -> {String data = success.getData();// Process successful response...}case ErrorResponse error -> {int errorCode = error.getErrorCode();String errorMessage = error.getErrorMessage();// Handle error response...}}
}

JDK17-instance of

if (obj instanceof String s) {System.out.println("String value: " + s);
} else if (obj instanceof Integer i) {System.out.println("Integer value: " + i);
}

JDK21-虚拟线程

import java.util.concurrent.Flow.Subscriber;
import java.util.concurrent.Flow.Subscription;
import java.util.concurrent.ForkJoinPool;
import jdk.incubator.foreign.MemorySegment;public class VirtualThreadExample {public static void main(String[] args) {// Create a virtual threadThread.startVirtualThread(() -> {// Your concurrent task here...});// Use Project Loom features like Structured Concurrency or Foreign Function Interface// ...// Alternatively, you can also create a virtual thread poolForkJoinPool virtualThreadPool = ForkJoinPool.commonPool();virtualThreadPool.submit(() -> {// Concurrent task executed on a virtual thread});}
}

JDK21-外部函数和内存API

import jdk.incubator.foreign.*;public class ForeignFunctionExample {public static void main(String[] args) throws Throwable {// Load a shared libraryLibraryLookup lookup = LibraryLookup.ofLibraryPath("/path/to/library.so");// Define function signatureFunctionDescriptor descriptor = FunctionDescriptor.ofVoid(CLinker.C_CHAR);// Obtain a symbol handle for the functionSymbolHandle symbol = lookup.lookup("my_function").get();// Create a memory segment to hold input dataMemorySegment inputBuffer = MemorySegment.allocateNative(1024, ResourceScope.newConfinedScope());try (ResourceScope scope = ResourceScope.newConfinedScope()) {// Call the foreign functionCLinker.systemCLinker().callVoid(symbol, inputBuffer);// Access memory contents after the callbyte resultByte = inputBuffer.getByte(0);System.out.println("Result byte: " + resultByte);}}
}

JDK21-Vector API

import jdk.incubator.vector.*;public class VectorApiExample {public static void main(String[] args) {// Create a vector of integersVectorSpecies<Integer> intSpec = IntVector.SPECIES_PREFERRED;VectorMask<Integer> mask = intSpec.indexInRange(0, 4).toMask();Vector<Integer> vec = Vector.fromArray(intSpec, new int[]{1, 2, 3, 4}, 0);// Perform vector operationsVector<Integer> squaredVec = vec.lanewise(VectorOperators.SQUARE);Vector<Integer> incrementedVec = vec.add(1);// Extract results back to arraysint[] squaredArray = new int[4];int[] incrementedArray = new int[4];squaredVec.intoArray(squaredArray, 0);incrementedVec.intoArray(incrementedArray, 0);System.out.println("Squared array: " + Arrays.toString(squaredArray));System.out.println("Incremented array: " + Arrays.toString(incrementedArray));}
}

各版本主要特性清单

JDK8(March 2014)

特性名称特性描述
Lambda Expressions引入了一种简洁的函数式编程语法,允许将函数作为参数传递,简化匿名内部类的使用。
Stream API提供了一种高效处理数据集合的方式,支持流式计算、聚合操作和并行处理。
Default Methods in Interfaces接口中可以定义默认方法(带有实现的抽象方法),便于在不破坏现有实现的情况下向接口添加新功能。
Method References与lambda表达式配合使用,提供了简洁的语法来引用已有方法或构造函数。
Optional Class用于表示可能为空的值,鼓励显式处理空值情况,避免NullPointerException。
Date and Time API (JSR 310)引入全新的日期和时间API,包括LocalDate、LocalTime、LocalDateTime、ZonedDateTime等类,提供了更好的日期和时间处理能力。
Nashorn JavaScript Engine内置高性能JavaScript引擎,支持在Java应用程序中执行JavaScript代码。
Compact Profiles提供了三个精简的JRE子集,适用于资源受限的设备。
Improved Type Annotations支持使用JSR 308规范的类型注解,增强编译时的类型检查和工具支持。
Concurrency Enhancements包括StampedLock、CompletableFuture、ForkJoinPool improvements等,增强了并发编程能力。

JDK 9 (September 2017)

特性名称特性描述
Jigsaw Project (Module System)引入模块化系统(Project Jigsaw),实现了JAR包的模块化打包和运行时的模块化加载,提高了可维护性和安全性。
Reactive Streams API (JSR 356)标准化了异步非阻塞数据流处理,为响应式编程提供基础。
HTTP/2 Client新的HTTP/2协议支持的HTTP客户端API,提供了更好的性能和更低的延迟。
Process API Updates更新了java.lang.Process API,增加了对进程输入/输出流的非阻塞访问。
Multi-Resolution Images支持多分辨率图像,改进了对高DPI显示器的支持。
JShell The Java REPL提供了一个交互式的Read-Eval-Print Loop (REPL),便于快速试验Java代码片段。

JDK 10 (March 2018)

特性名称特性描述
Local-Variable Type Inference (var keyword)引入关键字var,允许编译器推断局部变量的类型。
Garbage Collector Improvements对G1垃圾收集器进行了优化,包括并行Full GC和更细粒度的内存区域划分。
Application Class-Data Sharing扩展了Class Data Sharing (CDS),支持将应用类的元数据放入共享存档,减少启动时间和内存占用。

JDK 11 (September 2018)

特性名称特性描述
HTTP Client (Standard)将之前JDK 9的实验性HTTP/2客户端API升级为正式的标准API。
Low-Overhead Heap Profiling引入低开销堆分析工具(JFR-based),无需停顿 JVM 即可进行性能分析
Epsilon Garbage Collector (No-Op GC)实验性的无操作垃圾收集器,用于性能基准测试和其他特殊情况。
Flight Recorder开放 Flight Recorder(JFR)作为标准特性,提供详细的运行时监控和故障排除数据
ZGC引入实验性的Z Garbage Collector(ZGC),旨在提供低延迟(<10ms暂停时间)、高吞吐量和大堆支持。

JDK 12 (March 2019)

特性名称特性描述
Switch Expressions (Preview)引入了开关表达式作为switch语句的扩展,允许在switch块内使用箭头语法返回值,并支持多条case语句共享相同的执行体(JEP 325)。
Microbenchmark Suite提供了一个微基准测试工具JMH(Java Microbenchmark Harness),用于测量和比较代码片段的性能(JEP 328)。
JVM Constants API添加了一组标准API以反射地访问底层运行时的常量池(JEP 334)。

JDK 13 (September 2019)

特性名称特性描述
Switch Expressions (Standard)将JDK 12中预览的开关表达式转为正式功能(JEP 354)。
Text Blocks (Preview)引入文本块(multi-line string literals)以简化编写多行字符串和嵌入式引号的处理(JEP 355)。
ZGCZ Garbage Collector能够释放未使用的堆内存返回给操作系统(JEP 376)。

JDK 14 (March 2020)

特性名称特性描述
Text Blocks (Standard)文本块从预览功能升级为标准功能(JEP 368)
Pattern Matching for instanceof (Preview)引入模式匹配语法,允许在instanceof检查后直接解构对象(JEP 305)。
Packaging Tool提供一个简单命令行工具,用于创建自包含的可执行JAR文件(JEP 343)

JDK 15 (September 2020)

特性名称特性描述
Pattern Matching for instanceof (Standard)模式匹配语法从预览变为正式功能(JEP 375)
Shenandoah: A Low-Pause-Time Garbage CollectorShenandoah垃圾收集器成为正式可用选项,旨在降低GC暂停时间(JEP 378)
Hidden Classes支持创建隐藏类,仅能通过反射访问,主要用于框架和工具(JEP 371)。

JDK 16 (March 2021)

特性名称特性描述
Records引入记录类(Record Classes),作为一种简化的类声明形式,专注于不可变数据的封装(JEP 384)
Pattern Matching for switch Statements (Preview)扩展模式匹配语法至switch语句(JEP 394)。
Foreign-Memory Access API (Incubator)提供一组低级别的API,以安全、高效地访问Java程序外部的内存(JEP 383)。

JDK 17 (September 2021)

特性名称特性描述
Sealed Classes (Standard)密封类(Sealed Classes)正式推出,限制子类化范围,增强模块性和安全性(JEP 397)。
Pattern Matching for switch Statements (Standard)模式匹配语法扩展至switch语句,允许基于对象的类型进行更简洁、类型安全的选择分支(JEP 406)
Remove the Experimental AOT and JIT Compiler移除了实验性的AOT(Ahead-of-Time)编译器和部分JIT(Just-In-Time)编译器功能(JEP 410)

JDK 18 (March 2022)

特性名称特性描述
Vector API (Second Incubator)更新了向量计算API的第二个孵化器版本,提供了硬件加速的向量化计算能力(JEP 417)
Simple Web Server提供了一个简单的内置Web服务器,方便开发者快速启动静态网页服务或HTTP端点测试(JEP 408)

JDK 19 (September 2022)

特性名称特性描述
Virtual Threads (Preview)引入虚拟线程(Project Loom的一部分),这是一种轻量级线程实现,旨在提高大规模并发编程的效率(JEP 425)
Foreign Function & Memory API (Second Incubator)外部函数与内存API进入第二个孵化器阶段,增强了对C/C++本地代码和数据的访问能力(JEP 424)。
Structured Concurrency (Incubator)结构化并发API(Project Loom的一部分)进入孵化器,旨在简化异步编程模型,提升异常处理和资源管理的清晰度(JEP 428)。

JDK 20 (March 2023)

特性名称特性描述
Foreign Function & Memory API (Third Incubator)外部函数与内存API进入第三个孵化器阶段,继续完善其功能和稳定性(假设JEP编号延续,预计为JEP 442)。
Vector API (Third Preview)向量API进入第三个预览版,进一步优化并接近最终形态(假设JEP编号延续,预计为JEP 443)。

JDK 21 (September 2023)

特性名称特性描述
Foreign Function & Memory API (Standard)外部函数与内存API预计转为正式功能,提供稳定的跨语言互操作支持(假设JEP编号延续,预计为JEP 458)
Vector API (Standard)向量API预计转为正式功能,为高性能向量化计算提供标准化支持(假设JEP编号延续,预计为JEP 459)。

结语

本文整理了jdk8-jdk21各个版本的新特性信息,并给出了一些简单示例。

希望能帮助到需要的朋友。

创作不易,欢迎一键三连。

这篇关于【工作记录】JDK8到JDK21都更新了哪些新特性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/873672

相关文章

Spring Retry 实现乐观锁重试实践记录

《SpringRetry实现乐观锁重试实践记录》本文介绍了在秒杀商品SKU表中使用乐观锁和MybatisPlus配置乐观锁的方法,并分析了测试环境和生产环境的隔离级别对乐观锁的影响,通过简单验证,... 目录一、场景分析 二、简单验证 2.1、可重复读 2.2、读已提交 三、最佳实践 3.1、配置重试模板

在 Spring Boot 中使用异步线程时的 HttpServletRequest 复用问题记录

《在SpringBoot中使用异步线程时的HttpServletRequest复用问题记录》文章讨论了在SpringBoot中使用异步线程时,由于HttpServletRequest复用导致... 目录一、问题描述:异步线程操作导致请求复用时 Cookie 解析失败1. 场景背景2. 问题根源二、问题详细分

SpringBoot快速接入OpenAI大模型的方法(JDK8)

《SpringBoot快速接入OpenAI大模型的方法(JDK8)》本文介绍了如何使用AI4J快速接入OpenAI大模型,并展示了如何实现流式与非流式的输出,以及对函数调用的使用,AI4J支持JDK8... 目录使用AI4J快速接入OpenAI大模型介绍AI4J-github快速使用创建SpringBoot

Rust中的Drop特性之解读自动化资源清理的魔法

《Rust中的Drop特性之解读自动化资源清理的魔法》Rust通过Drop特性实现了自动清理机制,确保资源在对象超出作用域时自动释放,避免了手动管理资源时可能出现的内存泄漏或双重释放问题,智能指针如B... 目录自动清理机制:Rust 的析构函数提前释放资源:std::mem::drop android的妙

关于Spring @Bean 相同加载顺序不同结果不同的问题记录

《关于Spring@Bean相同加载顺序不同结果不同的问题记录》本文主要探讨了在Spring5.1.3.RELEASE版本下,当有两个全注解类定义相同类型的Bean时,由于加载顺序不同,最终生成的... 目录问题说明测试输出1测试输出2@Bean注解的BeanDefiChina编程nition加入时机总结问题说明

将sqlserver数据迁移到mysql的详细步骤记录

《将sqlserver数据迁移到mysql的详细步骤记录》:本文主要介绍将SQLServer数据迁移到MySQL的步骤,包括导出数据、转换数据格式和导入数据,通过示例和工具说明,帮助大家顺利完成... 目录前言一、导出SQL Server 数据二、转换数据格式为mysql兼容格式三、导入数据到MySQL数据

关于rpc长连接与短连接的思考记录

《关于rpc长连接与短连接的思考记录》文章总结了RPC项目中长连接和短连接的处理方式,包括RPC和HTTP的长连接与短连接的区别、TCP的保活机制、客户端与服务器的连接模式及其利弊分析,文章强调了在实... 目录rpc项目中的长连接与短连接的思考什么是rpc项目中的长连接和短连接与tcp和http的长连接短

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Python MySQL如何通过Binlog获取变更记录恢复数据

《PythonMySQL如何通过Binlog获取变更记录恢复数据》本文介绍了如何使用Python和pymysqlreplication库通过MySQL的二进制日志(Binlog)获取数据库的变更记录... 目录python mysql通过Binlog获取变更记录恢复数据1.安装pymysqlreplicat

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1