Java 迎来增强功能字符串模板,代码简化,安全性提升
面向 JDK 21 的 JEP 430(字符串模板预览)已经从 Proposed to Target 状态提升到 Targeted 状态。该 JEP 提议用字符串模板来增强 Java 编程语言。字符串模板类似于字符串字面量,但包含嵌入式表达式,这些表达式会在运行时合并到字符串模板中。
现在,Java 开发人员可以使用字符串模板增强该语言的字符串字面量和文本块。字符串模板将字面量文本与嵌入式表达式及处理器相结合,用于生成特定的结果。这一新特性的目的是简化 Java 程序的编写,提高文本和表达式混合代码的可读性,增强 Java 程序从用户提供的值组成字符串时的安全性。
该 JEP 引入了一种新的表达式,名为 模板表达式,让开发人员可以安全有效地执行字符串插值及组合字符串。模板表达式是可编程的,其功能并不限于组合字符串。它们可以根据特定于领域的规则将结构化文本转换为任何类型的对象。在模板表达式中,模板处理器在运行时将模板中的字面量文本与嵌入表达式的值组合在一起生成所需的结果。请看下面的例子:
String name = "Joan";
String info = STR."My name is \{name}";
assert info.equals("My name is Joan"); // true
模板表达式的语法与字符串字面量类似,但有一个前缀。上述代码的第二行包含一个模板表达式。
相比之下,字符串插值通常允许程序员将字符串字面量和表达式组合成单个字符串,就像许多编程语言所做的那样,与传统的字符串连接相比,这样更方便也更清晰。但是,它会生成可能被其他系统误解的危险字符串,特别是在处理 SQL 语句、HTML/XML 文档、JSON 片段、shell 脚本和自然语言文本时。为了防止安全漏洞,Java 要求开发人员使用转义或验证方法对带有嵌入式表达式的字符串进行验证和消毒。
更安全、更有效的解决方案是引入一种基于模板的一等字符串组合机制,该机制会自动将特定于模板的规则应用于字符串,为 SQL 语句添加转义引号,让 HTML 文档没有非法实体,以及实现无模板的消息本地化。这种方法使开发人员不用再手动对每个嵌入式表达式进行转义,并验证整个字符串。这正是 Java模板表达式所做的,与其他流行的编程语言所使用的字符串插值完全不同。
在模板表达式的设计中,包含嵌入式表达式的字符串字面量或文本块是不可能直接转换为插入了表达式值的字符串的。这是为了防止危险的错误字符串在程序中传播。取而代之,模板处理器(如 STR、FMT 或 RAW)会处理字符串字面量,验证结果,并插入嵌入式表达式的值。
下面是一些模板表达式的例子,它们使用多行来描述 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 form = 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
| "
Java 提供了两个模板处理器来执行字符串插值:STR
和FMT
。STR
用它(字符串化)的值替换模板中的每个嵌入式表达式,而FMT
会解释出现在嵌入式表达式左侧的格式说明符。格式说明符与java.util.Formatter
中定义的格式说明符相同。如果需要未经处理的原始模板,则可以使用标准的RAW
模板处理器。这个处理器只是简单地返回原始模板,不做任何插值或处理。
此外,开发人员还可以创建自己的模板处理器,用于模板表达式的处理。模板处理器是一个提供ValidatingProcessor
功能接口的对象,它的类实现了ValidatingProcessor
的单一抽象方法。该方法接受StringTemplate
并返回一个对象。自定义模板处理器让开发人员可以在运行时执行验证并返回任何类型的对象,而不仅仅是字符串。
总之,Java 模板表达式使开发人员可以轻松、安全地进行字符串插值和字符串组合。
原文链接:
https://www.infoq.com/news/2023/04/java-gets-a-boost-with-string/
相关阅读:
Java 近期新闻:Java 28 岁、Payara、Micronaut 4.0-M5、Spring 更新 (https://www.infoq.cn/article/eazviIX3Dutuh3lKwd1F)
快速实现不打折扣的云原生 Java 应用 (https://www.infoq.cn/article/R8sh9XHuojBsX9DpGYvJ)
Record 模式提升了 Java,能实现更具表现力的编码](https://www.infoq.cn/article/0ZTAForQs79EseZhPRXU)
声明:本文为 InfoQ 翻译,未经许可禁止转载。
点击底部阅读原文访问 InfoQ 官网,获取更多精彩内容!
市值暴涨10519%,原来全世界搞大模型的企业都在给这位华人打工!
百度推出生成式AI代码助手,覆盖 30 种编程语言;高考生喊话马化腾,腾讯回应;机房宕机损失过亿,唯品会负责人被免职 | Q资讯
微信扫码关注该文公众号作者