JDK 21 发布,新特性概览及字符串模板详细介绍

这篇具有很好参考价值的文章主要介绍了JDK 21 发布,新特性概览及字符串模板详细介绍。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、新特性概览

Java 21 已于 2023 年 9 月 19 日发布,是 Oracle 标准 Java 实现的下一个长期支持(LTS)版本。Java 21 具有以下 15 项新特性。

  • 430: String Templates (Preview)
    字符串模板,可以像其他语言那样子方便的做字符串拼接,是+号,StringBuilder,MessageFormat之外更方便的字符串拼接方法。
  • 431: Sequenced Collections
    引入新的接口来表示具有定义相遇顺序的集合。每个这样的集合都有定义明确的第一个元素、第二个元素,以此类推,直到最后一个元素。它还提供了统一的应用程序接口,用于访问其第一个和最后一个元素,以及以相反的顺序处理其元素。
  • 439: Generational ZGC
    通过扩展 Z 垃圾收集器(ZGC),为新旧对象分别保留不同的世代,从而提高应用程序的性能。这将允许 ZGC 更频繁地收集年轻代的对象(对象往往频繁地英年早逝)。
  • 440: Record Patterns
    使用记录模式来解构记录值,从而增强 Java 编程语言的功能。记录模式和类型模式可以嵌套,以实现强大、声明性和可组合的数据导航和处理形式。
  • 441: Pattern Matching for switch
    用模式匹配来增强 Java 编程语言的开关表达式和语句。将模式匹配扩展到开关后,表达式就可以根据多个模式(每个模式都有特定的操作)进行测试,从而可以简洁安全地表达面向数据的复杂查询。
  • 442: Foreign Function & Memory API (Third Preview)
    引入一个应用程序接口(API),使 Java 程序能够与 Java 运行时之外的代码和数据互操作。通过高效地调用外来函数(即 JVM 之外的代码)和安全地访问外来内存(即 JVM 管理之外的内存),API 使 Java 程序能够调用本地库和处理本地数据,而不会出现 JNI 的脆性和危险。这是一个预览版 API。
  • 443: Unnamed Patterns and Variables (Preview)
    使用未命名模式和未命名变量来增强 Java 语言的功能。未命名模式用于匹配记录组件,但不说明该组件的名称或类型;未命名变量用于初始化但不使用。两者都用下划线字符 _ 表示。这是一项预览语言功能。
  • 444: Virtual Threads
    将虚拟线程引入 Java 平台。虚拟线程是一种轻量级线程,可大大减少编写、维护和观察高吞吐量并发应用程序的工作量。
  • 445: Unnamed Classes and Instance Main Methods (Preview)
    使学生无需了解专为大型程序设计的语言功能,即可编写自己的第一个程序。与使用单独的 Java 不同,学生可以为单类程序编写精简的声明,然后随着技能的提高无缝扩展他们的程序,使用更高级的功能。这是一项预览语言功能。
  • 446: Scoped Values (Preview)
    引入作用域值,即无需使用方法参数即可安全高效地共享给方法的值。与线程本地变量相比,它们更受青睐,尤其是在使用大量虚拟线程时。这是一个预览版 API。
  • 448: Vector API (Sixth Incubator)
    引入一个应用程序接口来表达矢量计算,在运行时可靠地编译成支持的 CPU 架构上的最佳矢量指令,从而实现优于同等标量计算的性能。
  • 449: Deprecate the Windows 32-bit x86 Port for Removal
    弃用32位x86的Windows发行
  • 451: Prepare to Disallow the Dynamic Loading of Agents
    当代理被动态加载到运行中的 JVM 时发出警告。这些警告的目的是让用户做好准备,以便在未来的版本中默认禁止动态加载代理,从而提高默认情况下的完整性。在启动时加载代理的服务性工具在任何版本中都不会发出警告。
  • 452: Key Encapsulation Mechanism API
    引入密钥封装机制(KEM)的API接口,这是一种使用公钥加密法确保对称密钥安全的加密技术。
  • 453: Structured Concurrency (Preview)
    通过引入结构化并发 API 来简化并发编程。结构化并发将在不同线程中运行的一组相关任务视为一个工作单元,从而简化了错误处理和取消,提高了可靠性并增强了可观察性。这是一个预览版 API。

二、有特色的特性介绍

2.1. 字符串模板 430: String Templates (Preview)

这个特性虽然还在预览阶段,还不属于正式发布,但是若能最终进入发布,能够大大减轻了Java编程时复杂字符串的编辑处理工作量。

2.1.1. 该特性的设计目标是

  • 通过简单的方式表达混合变量的字符串,简化 Java 程序的编写。
  • 提高混合文本和表达式的可读性,无论文本是在单行源代码中(如字符串字面量)还是跨越多行源代码(如文本块)。
  • 通过支持对模板及其嵌入式表达式的值进行验证和转换,提高根据用户提供的值组成字符串并将其传递给其他系统(如构建数据库查询)的 Java 程序的安全性。
  • 允许 Java 库定义字符串模板中使用的格式化语法(java.util.Formatter ),从而保持灵活性。
  • 简化接受以非 Java 语言编写的字符串(如 SQL、XML 和 JSON)的 API 的使用。
  • 支持创建由字面文本和嵌入式表达式计算得出的非字符串值,而无需通过中间字符串表示。

2.1.2. 不是什么

  • 我们的目标不是为 Java 的字符串连接操作符 (+) 引入语法增强。
  • 我们的目标不是废弃或移除 StringBuilder 和 StringBuffer 类,这两个类历来用于复杂或程序化的字符串组合。

2.1.3. 动机

开发人员经常使用字面文本和表达式组合来组成字符串。Java 提供了多种字符串组合机制,但遗憾的是,所有机制都有缺点。

  • 使用 + 运算符进行字符串连接会产生难以阅读的代码:
String s = x + " plus " + y + " equals " + (x + y);
  • StringBuilder
String s = new StringBuilder()
                 .append(x)
                 .append(" plus ")
                 .append(y)
                 .append(" equals ")
                 .append(x + y)
                 .toString();
  • String::format 和 String::formatted 将格式字符串从参数中分离出来
String s = String.format("%2$d plus %1$d equals %3$d", x, y, x + y);
String t = "%2$d plus %1$d equals %3$d".formatted(x, y, x + y);
  • java.text.MessageFormat 需要在格式字符串中使用不方便代码阅读的数字索引,当变量数量多了,无法快速阅读
MessageFormat mf = new MessageFormat("{0} plus {1} equals {2}");
String s = mf.format(x, y, x + y);

2.1.4. 设计说明

模板表达式(Template expressions)是 Java 编程语言中的一种新型表达式。模板表达式不仅可以执行字符串插值,还可以编程,从而帮助开发人员安全高效地组成字符串。此外,模板表达式并不局限于组成字符串——它们可以根据特定领域的规则将结构化文本转化为任何类型的对象。

2.1.4.1. STR 模板处理器

STR 是 Java 平台定义的一种模板处理器。它通过用表达式的(stringified)值替换模板中的每个嵌入表达式来执行字符串插值。使用 STR 的模板表达式的求值结果是一个字符串。

STR 是一个公共静态 final 字段,会自动导入到每个 Java 源文件中。

  • 下面是更多使用 STR 模板处理器的模板表达式示例。
// Embedded expressions can be strings
String firstName = "Bill";
String lastName  = "Duck";
String fullName  = STR."\{firstName} \{lastName}";
程序结果:Bill Duck
String sortName  = STR."\{lastName}, \{firstName}";
程序结果:Duck, Bill

// Embedded expressions can perform arithmetic
int x = 10, y = 20;
String s = STR."\{x} + \{y} = \{x + y}";
程序结果:"10 + 20 = 30"

// Embedded expressions can invoke methods and access fields
String s = STR."You have a \{getOfferType()} waiting for you!";
程序结果:"You have a gift waiting for you!"
String t = STR."Access at \{req.date} \{req.time} from \{req.ipAddress}";
程序结果:Access at 2022-03-25 15:34 from 8.8.8.8
  • 重构+号拼接的字符串的示例
String filePath = "tmp.dat";
File   file     = new File(filePath);
String old = "The file " + filePath + " " + (file.exists() ? "does" : "does not") + " exist";
String msg = STR."The file \{filePath} \{file.exists() ? "does" : "does not"} exist";
程序结果:The file tmp.dat does exist
或者是:The file tmp.dat does not exist
  • 为了提高可读性,嵌入式表达式可以在源文件中多行显示,而不会在结果中引入换行符。嵌入式表达式的值将在嵌入式表达式的位置插值到结果中。例如:
String time = STR."The time is \{
    // The java.time.format package is very useful
    DateTimeFormatter
      .ofPattern("HH:mm:ss")
      .format(LocalTime.now())
} right now";
程序结果:The time is 12:34:56 right now
  • 字符串模板表达式中的嵌入表达式数量没有限制。嵌入式表达式从左到右依次求值,就像方法调用表达式中的参数一样。例如:
// Embedded expressions can be postfix increment expressions
int index = 0;
String data = STR."\{index++}, \{index++}, \{index++}, \{index++}";
程序结果:"0, 1, 2, 3"
  • 任何 Java 表达式都可以用作嵌入式表达式,甚至是模板表达式。例如
// Embedded expression is a (nested) template expression
String[] fruit = { "apples", "oranges", "peaches" };
String s = STR."\{fruit[0]}, \{STR."\{fruit[1]}, \{fruit[2]}"}";
程序结果:apples, oranges, peaches

上面的代码fruit[1]和fruit[2]所在的模板被嵌入,是不是读起来非常困难,可以优化成这样:

String s = STR."\{fruit[0]}, \{
    STR."\{fruit[1]}, \{fruit[2]}"
}";

也可以这样:

String tmp = STR."\{fruit[1]}, \{fruit[2]}";
String s = STR."\{fruit[0]}, \{tmp}";
2.1.4.1.1. 多行模板表达式

模板表达式的模板可以跨越多行源代码,使用的语法与文本块类似。(我们在上文看到了一个跨多行的嵌入式表达式,但包含该嵌入式表达式的模板在逻辑上只有一行)。

以下是表示 HTML 文本、JSON 文本和区域表的模板表达式的示例,它们都跨多行:

String title = "My Web Page";
String text  = "Hello, world";
String html = STR."""
        <html>
          <head>
            <title>\{title}</title>
          </head>
          <body>
            <p>\{text}</p>
          </body>
        </html>
        """;
程序结果: 
 <html>
   <head>
     <title>My Web Page</title>
   </head>
   <body>
     <p>Hello, world</p>
   </body>
 </html>


String name    = "Joan Smith";
String phone   = "555-123-4567";
String address = "1 Maple Drive, Anytown";
String json = STR."""
    {
        "name":    "\{name}",
        "phone":   "\{phone}",
        "address": "\{address}"
    }
    """;
程序结果:
 {
     "name":    "Joan Smith",
     "phone":   "555-123-4567",
     "address": "1 Maple Drive, Anytown"
 }


record Rectangle(String name, double width, double height) {
    double area() {
        return width * height;
    }
}
Rectangle[] zone = new Rectangle[] {
    new Rectangle("Alfa", 17.8, 31.4),
    new Rectangle("Bravo", 9.6, 12.4),
    new Rectangle("Charlie", 7.1, 11.23),
};
String table = STR."""
    Description  Width  Height  Area
    \{zone[0].name}  \{zone[0].width}  \{zone[0].height}     \{zone[0].area()}
    \{zone[1].name}  \{zone[1].width}  \{zone[1].height}     \{zone[1].area()}
    \{zone[2].name}  \{zone[2].width}  \{zone[2].height}     \{zone[2].area()}
    Total \{zone[0].area() + zone[1].area() + zone[2].area()}
    """;
程序结果:
 Description  Width  Height  Area
 Alfa  17.8  31.4     558.92
 Bravo  9.6  12.4     119.03999999999999
 Charlie  7.1  11.23     79.733
 Total 757.693
2.1.4.2. FMT 模板处理器

FMT 是 Java 平台定义的另一种模板处理器。FMT 与 STR 类似,它执行插值,但也解释嵌入表达式左侧出现的格式规范。

FMT 需要手动执行导入

import static java.util.FormatProcessor.FMT;

格式说明符与 java.util.Formatter 中定义的格式说明符相同。例如:

record Rectangle(String name, double width, double height) {
    double area() {
        return width * height;
    }
}
Rectangle[] zone = new Rectangle[] {
    new Rectangle("Alfa", 17.8, 31.4),
    new Rectangle("Bravo", 9.6, 12.4),
    new Rectangle("Charlie", 7.1, 11.23),
};
String table = FMT."""
    Description     Width    Height     Area
    %-12s\{zone[0].name}  %7.2f\{zone[0].width}  %7.2f\{zone[0].height}     %7.2f\{zone[0].area()}
    %-12s\{zone[1].name}  %7.2f\{zone[1].width}  %7.2f\{zone[1].height}     %7.2f\{zone[1].area()}
    %-12s\{zone[2].name}  %7.2f\{zone[2].width}  %7.2f\{zone[2].height}     %7.2f\{zone[2].area()}
    \{" ".repeat(28)} Total %7.2f\{zone[0].area() + zone[1].area() + zone[2].area()}
    """;
程序输出:
Description     Width    Height     Area
Alfa            17.80    31.40      558.92
Bravo            9.60    12.40      119.04
Charlie          7.10    11.23       79.73
                              Total  757.69

2.1.5. 其他说明

模板处理器在运行时执行,而不是在编译时执行,因此无法对模板进行编译时处理。它们也无法获得源代码中出现在模板中的确切字符;只能获得嵌入式表达式的值,而不能获得嵌入式表达式本身。

支持用户定义的模板处理器。前面我们看到了模板处理器 STR 和 FMT,它们让人觉得模板处理器是一个通过字段访问的对象。其实,模板处理器是一个对象,它是方法接口 StringTemplate.Processor 的实例。开发人员可以轻松创建模板处理器,用于模板表达式。

!!!注意不要把字符串模板功能用于SQL拼接,稍不注意就引入了SQL注入风险

!!!另外要特别提醒的是,这个特性目前还在Preview状态,还没有正式发布,请不要用于生产环境。只是感叹Java还在不停的改进,学习其他语言优秀的地方,是广大开发者的福音

下一篇

JDK21新特性之虚拟线程

后续整理代际ZGC439: Generational ZGC文章来源地址https://www.toymoban.com/news/detail-784728.html

到了这里,关于JDK 21 发布,新特性概览及字符串模板详细介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JDK 21预告:虚拟线程正式发布及十多项新特性

    Java 21进入发布候选阶段,其中包括15个最终特性,包括虚拟线程、分代Z垃圾收集器和密钥封装机制API。 JDK21计划于9月19日作为Oracle标准Java实现的下一个LTS版本发布,已进入发布候选(RC)阶段。Java 21将具有15个新特性,之前提议的第16个特性实验性Shenandoah垃圾收集器已在6月被舍

    2024年02月10日
    浏览(34)
  • 【Kotlin】字符串操作 ① ( 截取字符串函数 substring | 拆分字符串函数 split | 解构语法特性 )

    Kotlin 中提供了 截取字符串函数 substring , 可接收 IntRange 类型的参数 , 这是 整数范围 类型 ; 截取字符串函数 substring 函数原型为 : 整数范围类型 : 其整数范围是 {0 , 1 , 2 , 3} ; 其整数范围是 {0 , 1 , 2} ; 代码示例 : 执行结果 : 拆分字符串函数 split 返回的是 List 集合 ; 拆分字符串函

    2023年04月08日
    浏览(43)
  • LeeCode前端算法基础100题(21) 同构字符串

    一、问题详情: 给定两个字符串  s  和  t  ,判断它们是否是同构的。 如果  s  中的字符可以按某种映射关系替换得到  t  ,那么这两个字符串是同构的。 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只

    2024年01月19日
    浏览(31)
  • 选读SQL经典实例笔记21_字符串处理

    2024年02月13日
    浏览(78)
  • [Week 21] 每日一题(C++,数学,二分,字符串,STL)

    目录 T1 [Daimayuan] 一半相等(C++,数学) 输入格式 输出格式 样例输入 样例输出 数据规模 解题思路 T2 [Daimayuan] 兔纸(C++,二分) 题目背景 题目描述 输入格式 输出格式 样例输入 样例输出 数据范围 附加说明 解题思路 T3 [Daimayuan] 添加括号(C++,数学) 输入格式 输出格式 数

    2024年02月09日
    浏览(34)
  • 【面试算法——动态规划 21】正则表达式匹配(hard)&& 交错字符串

    链接: 10. 正则表达式匹配 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 ‘.’ 和 ‘*’ 的正则表达式匹配。 ‘.’ 匹配任意单个字符 ‘*’ 匹配零个或多个前面的那一个元素 所谓匹配,是要涵盖 整个 字符串 s的,而不是部分字符串。 示例 1: 输入:s = “aa”

    2024年02月08日
    浏览(37)
  • JS--es6模板字符串

    一、模板字符串空格 二、模板字符串换行 1.转义 2.缩进换行

    2024年02月16日
    浏览(39)
  • P3375 【模板】KMP 字符串匹配

    给出两个字符串 s 1 s_1 s 1 ​ 和 s 2 s_2 s 2 ​ ,若 s 1 s_1 s 1 ​ 的区间 [ l , r ] [l, r] [ l , r ] 子串与 s 2 s_2 s 2 ​ 完全相同,则称 s 2 s_2 s 2 ​ 在 s 1 s_1 s 1 ​ 中出现了,其出现位置为 l l l 。 现在请你求出 s 2 s_2 s 2 ​ 在 s 1 s_1 s 1 ​ 中所有出现的位置。 定义一个字符串 s s s 的

    2024年02月14日
    浏览(39)
  • Leetcode每日一题:2337. 移动片段得到字符串(2023.8.21 C++)

    目录 2337. 移动片段得到字符串 题目描述: 实现代码与解析: 双指针 原理思路:         给你两个字符串  start  和  target  ,长度均为  n  。每个字符串  仅  由字符  \\\'L\\\' 、 \\\'R\\\'  和  \\\'_\\\'  组成,其中: 字符  \\\'L\\\'  和  \\\'R\\\'  表示片段,其中片段  \\\'L\\\'  只有在其左侧直接

    2024年02月11日
    浏览(28)
  • 记录-Vue.js模板编译过程揭秘:从模板字符串到渲染函数

    Vue.js是一个基于组件化和响应式数据流的前端框架。当我们在Vue中编写模板代码时,它会被Vue编译器处理并转换为可被浏览器解析的JavaScript代码。Vue中的模板实际上是HTML标记和Vue指令的组合,它们会被Vue编译器处理并转化为一个JavaScript渲染函数。 Vue中的模板编译分为两个阶

    2023年04月14日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包