欢迎光临
我们一直在努力

盘点JDK13的新特性

目录

一、语言特性:2个预览功能,简化编码效率

1. Switch表达式(预览,JEP 354)

代码对比(直观感受优化)

2. 文本块(预览,JEP 355)

代码对比

二、JVM优化:2个核心特性,提升性能与可用性

1. 动态CDS归档(JEP 350)

使用示例(关键命令)

2. ZGC增强:释放未使用内存(JEP 351)

核心原理与使用

三、API优化:1个核心重构,提升可维护性

重新实现Socket API(JEP 353)

核心优势

四、其他补充:Unicode 12.1支持

五、总结与实践建议


        JDK13作为Java生态的重要迭代版本,于2019年9月17日全球首发,虽然它并非长期支持(LTS)版本,但带来了多个实用的新特性和优化,涵盖语言语法、JVM性能、API实现等多个维度,极大提升了开发效率和系统性能。今天就带大家全面盘点JDK13的核心新特性,结合代码示例和实际应用场景,帮大家快速掌握其用法和价值。

        先明确一个前提:JDK13包含5个正式JEP(Java Enhancement Proposals)和Unicode 12.1支持,共6大核心特性,其中2个为预览语言功能(需手动启用),其余均为正式可用特性。下面我们逐一拆解,干货满满,建议收藏备用~

一、语言特性:2个预览功能,简化编码效率

        预览特性是Java为了收集开发者反馈而推出的实验性功能,默认不启用,需通过JVM参数开启(–enable-preview)。JDK13的两个预览特性均围绕“简化编码”展开,后续在JDK14中得到进一步完善。

1. Switch表达式(预览,JEP 354)

        Switch表达式并非JDK13首次引入,其在JDK12中已作为预览特性出现,JDK13对其进行了优化,允许Switch表达式既可以作为语句使用,也可以作为表达式返回值,同时支持传统case标签(带穿透)和新case标签(不带穿透),还新增了yield关键字用于返回表达式结果。

在JDK13之前,Switch语句存在两个痛点:一是case穿透容易引发bug,二是无法直接返回值,需额外定义变量接收结果。而Switch表达式完美解决了这两个问题。

代码对比(直观感受优化)

JDK13之前的传统写法:

// 传统Switch语句,需定义变量接收结果,且存在case穿透风险 public static String getWeekDesc(int day) { String desc; switch (day) { case 1: case 7: desc = "周末"; break; case 2: case 3: case 4: case 5: case 6: desc = "工作日"; break; default: desc = "无效日期"; break; } return desc; }

JDK13 Switch表达式写法:

// 启用预览功能后,Switch可直接返回值,使用->避免穿透,yield返回结果 public static String getWeekDesc(int day) { return switch (day) { case 1, 7 -> "周末"; case 2, 3, 4, 5, 6 -> "工作日"; default -> { System.out.println("输入日期无效"); yield "无效日期"; // 用yield返回表达式结果 } }; }

核心优势:① 简化代码,减少break关键字的使用,避免穿透bug;② 支持多case合并(用逗号分隔);③ 可直接作为表达式返回值,无需额外定义变量;④ 复杂case逻辑可通过代码块+yield返回结果,灵活性更高。

2. 文本块(预览,JEP 355)

在日常开发中,我们经常需要编写多行字符串(如HTML、SQL、JSON等),JDK13之前,多行字符串需使用“+”拼接,且需要手动添加换行符(\\n),不仅编写繁琐,可读性极差,还容易出现拼接错误。

文本块特性通过三重双引号(""")包裹多行内容,自动保留换行和缩进,无需手动拼接和添加换行符,极大提升了多行字符串的编写效率和可读性。

代码对比

JDK13之前的多行字符串写法:

// 拼接繁琐,可读性差,容易遗漏换行符 String html = "<html>\\n" + " <body>\\n" + " <p>Hello, JDK13!</p>\\n" + " </body>\\n" + "</html>"; String sql = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`\\n" + "WHERE `CITY` = 'INDIANAPOLIS'\\n" + "ORDER BY `EMP_ID`, `LAST_NAME`;"; }

JDK13文本块写法:

// 三重双引号包裹,自动保留换行和缩进,无需拼接 String html = """ <html> <body> <p>Hello, JDK13!</p> </body> </html>"""; String sql = """ SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB` WHERE `CITY` = 'INDIANAPOLIS' ORDER BY `EMP_ID`, `LAST_NAME`;"""; }

核心细节:① 文本块以"""开头,结束时"""需单独一行(可紧跟内容,也可换行);② 自动忽略开头的空行,保留内容的缩进结构;③ 若需取消自动换行,可在每行末尾添加反斜杠(\\);④ 支持转义字符(如\\t、\\b),与普通字符串一致。

二、JVM优化:2个核心特性,提升性能与可用性

JDK13对JVM进行了两项重要优化,分别针对CDS归档和ZGC垃圾收集器,聚焦于“启动速度”和“内存占用”两个核心痛点,尤其适配容器化环境和高并发场景。

1. 动态CDS归档(JEP 350)

CDS(Class-Data Sharing,类数据共享)是Java的一项经典优化,目的是通过共享不同Java进程之间的通用类元数据,减少内存占用、提升应用启动速度。在JDK13之前,使用AppCDS(应用类数据共享)需要三步操作:试运行创建类列表、根据类列表生成归档文件、使用归档文件启动应用,流程繁琐,且仅支持内置类加载器,对自定义类加载器的支持不完善。

动态CDS归档的核心作用的是简化AppCDS的使用流程,消除试运行步骤,同时统一支持内置类加载器和用户自定义类加载器,甚至可在应用第一次运行时自动生成归档文件,让CDS的使用变得透明、高效。

使用示例(关键命令)

# 1. 应用退出时,动态创建共享归档文件(hello.jsa为归档文件名) bin/java -XX:ArchiveClassesAtExit=hello.jsa -cp hello.jar Hello # 2. 使用动态生成的归档文件启动应用,提升启动速度和内存利用率 bin/java -XX:SharedArchiveFile=hello.jsa -cp hello.jar Hello

核心优势:① 简化操作流程,无需手动创建类列表;② 支持自定义类加载器,适配更多应用场景;③ 后续可实现自动生成归档,完全无需开发者干预;④ 进一步降低多JVM进程的内存占用,提升启动速度。

2. ZGC增强:释放未使用内存(JEP 351)

ZGC(Z Garbage Collector)是JDK11引入的一款低延迟垃圾收集器,主打“低停顿、高吞吐量”,但JDK11和JDK12中的ZGC存在一个问题:即使内存长时间未使用,也不会将其释放给操作系统,类似“貔貅只进不出”,这在容器化环境(按需付费)、多应用共享资源的场景中,会造成内存浪费。

JDK13对ZGC进行了增强,新增“释放未使用内存”的功能,可将长时间未使用的堆内存自动归还给操作系统,优化内存占用,尤其适配容器化、云原生场景。

核心原理与使用

ZGC的堆由多个ZPage(堆区域)组成,当ZGC进行堆压缩时,ZPage会被释放并放入ZPageCache(页面缓存)。页面缓存中的ZPage会以LRU(最近最少使用)顺序排序,当ZPage在缓存中停留时间超过阈值时,会被逐出并释放内存给操作系统。

关键参数:

  • -XX:ZUncommitDelay=seconds:设置ZPage在缓存中的停留阈值(默认值合理,可手动调整);

  • -XX:-ZUncommit:禁用内存释放功能(默认启用);

  • 注意:若设置-Xms(最小堆)与-Xmx(最大堆)相等,内存释放功能会失效(因为堆大小固定)。

适用场景:容器化应用、长时间闲置的应用、堆内存需求波动较大的应用(如启动时需要大堆,稳定运行后需要小堆)。

三、API优化:1个核心重构,提升可维护性

重新实现Socket API(JEP 353)

java.net.Socket和java.net.ServerSocket是Java最早的API之一,可追溯到JDK1.0,其底层实现基于PlainSocketImpl,混合了Java和C代码,不仅维护和调试困难,还存在诸多问题:使用线程栈作为I/O缓冲区(需调大Xss参数)、依赖本机数据结构导致可靠性问题、并发性能不佳,且无法适配未来的Project Loom(纤程)。

JDK13用全新的NioSocketImpl替代了PlainSocketImpl,重构了Socket API的底层实现,带来了多重优化。

核心优势
  • 简化实现:完全基于Java NIO,无需原生C代码,维护和调试更简单;

  • 性能优化:集成缓冲区缓存机制,无需使用线程栈进行I/O操作,减少资源消耗;

  • 并发提升:使用java.util.concurrent锁替代synchronized方法,适配纤程,支持更高并发;

  • 兼容性:上层API完全不变,开发者无需修改代码,即可享受优化带来的收益。

注意:该特性为底层实现重构,对开发者透明,无需额外操作,升级JDK13后即可自动生效。

四、其他补充:Unicode 12.1支持

除了上述5个JEP,JDK13还新增了对Unicode 12.1的支持,主要包括:

  • java.lang.Character支持Unicode 12.1字符数据库,相比Unicode 12.0新增1个字符(U+32FF,即日本令和时代标识),累计支持137,928个字符;

  • java.text.Bidi、java.text.Normalizer类支持Unicode 12.0对应的标准附件;

  • java.util.regex包支持基于Unicode 12.0的扩展字素集群,提升正则表达式对多语言字符的匹配能力。

该特性主要适配多语言场景,尤其是涉及日语、特殊符号的开发需求,开发者无需额外操作,直接使用相关API即可。

五、总结与实践建议

JDK13虽然不是LTS版本,但它的多个特性都极具实用价值,尤其是文本块、动态CDS归档、ZGC内存释放这三个特性,能直接解决开发和运维中的实际痛点:

  • 对于开发者:文本块和Switch表达式可直接简化编码,提升开发效率,建议在非生产环境尝试(预览特性需启用参数);

  • 对于运维/架构师:动态CDS归档可提升应用启动速度、降低内存占用,ZGC增强适配容器化环境,适合在高并发、内存敏感的场景中使用;

  • 兼容性:JDK13向下兼容,大部分现有项目无需修改代码即可升级,仅需注意预览特性的启用方式和Socket API的底层变化(对上层无影响)。

  • 最后提醒:由于JDK13不是LTS版本,不建议用于生产环境(生产环境优先选择JDK11、JDK17等LTS版本),但可以在开发、测试环境中使用,提前熟悉特性,为后续升级到更高版本的LTS版本做好准备。

    如果觉得本文对你有帮助,欢迎点赞、收藏、转发,也可以在评论区留言讨论JDK13的使用心得~

    赞(0)
    未经允许不得转载:171主机测评 » 盘点JDK13的新特性
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址