【工作记录】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

相关文章

Servlet中配置和使用过滤器的步骤记录

《Servlet中配置和使用过滤器的步骤记录》:本文主要介绍在Servlet中配置和使用过滤器的方法,包括创建过滤器类、配置过滤器以及在Web应用中使用过滤器等步骤,文中通过代码介绍的非常详细,需... 目录创建过滤器类配置过滤器使用过滤器总结在Servlet中配置和使用过滤器主要包括创建过滤器类、配置过滤

Ubuntu 24.04 LTS怎么关闭 Ubuntu Pro 更新提示弹窗?

《Ubuntu24.04LTS怎么关闭UbuntuPro更新提示弹窗?》Ubuntu每次开机都会弹窗提示安全更新,设置里最多只能取消自动下载,自动更新,但无法做到直接让自动更新的弹窗不出现,... 如果你正在使用 Ubuntu 24.04 LTS,可能会注意到——在使用「软件更新器」或运行 APT 命令时,

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

python与QT联合的详细步骤记录

《python与QT联合的详细步骤记录》:本文主要介绍python与QT联合的详细步骤,文章还展示了如何在Python中调用QT的.ui文件来实现GUI界面,并介绍了多窗口的应用,文中通过代码介绍... 目录一、文章简介二、安装pyqt5三、GUI页面设计四、python的使用python文件创建pytho

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

AI行业应用(不定期更新)

ChatPDF 可以让你上传一个 PDF 文件,然后针对这个 PDF 进行小结和提问。你可以把各种各样你要研究的分析报告交给它,快速获取到想要知道的信息。https://www.chatpdf.com/

GIS图形库更新2024.8.4-9.9

更多精彩内容请访问 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信:digital_twin123 Cesium 本期发布了1.121 版本。重大新闻,Cesium被Bentley收购。 ✨ 功能和改进 默认启用 MSAA,采样 4 次。若要关闭 MSAA,则可以设置scene.msaaSamples = 1。但是通过比较,发现并没有多大改善。