本文主要是介绍【工作记录】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)。 |
ZGC | Z 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 Collector | Shenandoah垃圾收集器成为正式可用选项,旨在降低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都更新了哪些新特性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!