好用!期待已久的文本块功能究竟如何在 Java 13 中发挥作用?

简介: 这可能是很多朋友目前的真实情况。说实话,Java “每半年发布一个新版本”的节奏确实快了点。但不管怎样,新技术、新特性还是值得我们学一学。

你继续半年一更,我继续用 Java 7/8。


这可能是很多朋友目前的真实情况。说实话,Java “每半年发布一个新版本”的节奏确实快了点。但不管怎样,新技术、新特性还是值得我们学一学。


在 Java 13 中,有了文本块,我们可以轻松地使用多行字符串。我们不再需要对字符串中的特殊字符进行转义,也不必对跨越多行的字符串使用 + 串联运算符,它极大地提高代码的可读性。在这篇文章中,我将介绍关于 Java 13 文本块的功能以及使用场景,一起来看看吧。


什么是文本块?


String 数据类型可能是 Java 开发人员最常用的类型之一。它可以以任何语言存储从几个字符到多行的所有内容。不过,这种灵活性也导致某些 String 值难以阅读或修改。例如,那些带有引号,转义字符或跨越多行的字符串。


文本块是 Java 13 的一项预览功能,我们可以使用文本块轻松定义多行字符串而无须添加串联运算符和转义字符。此外,我们还可以控制如何格式化字符串值。


让我们看看以下 HTML 代码段:


String html = """<HTML>  <BODY>    <H1>"Java 13 is here!"</H1>  </BODY></HTML>""";


注意,三个双引号 """ 分别定义了块的开始和结尾。看一下在 Java 13 以前是如何定义的:


String html =   "<HTML>\n\t<BODY>\n\t\t<H1>\"Java 13 is here!\"</H1> \n\t</BODY>\n</HTML>\n";


或者,更加典型的是:


String html = "<HTML>" +"\n\t" + "<BODY>" +"\n\t\t" + "<H1>\"Java 13 is here!\"</H1>" +"\n\t" + "</BODY>" +"\n" + "</HTML>";


上面的这两种写法,在可读性上远远不如不如文本块。


文本块语法


就像前面提到的,Java 13 使用三个双引号 """ 作为开始和结束定界符来定义文本块。开始定界符后面可以跟零个或者多个空格一个行终止符结束符没有类似的规则


这样的语法规则,导致以下示例其实是无效的文本块因为它们在开头定界符之后并没有包含一个行终止符


String multilineValue1 = """ """;String multilineValue2 = """""";


这只是预览特性


文本块在 Java 13 中作为预览特性发布,但预览特性并不意味着它是不完整或半生不熟的功能。从本质上讲,这意味着即使开发人员可以使用此功能,它也可能在将来的 Java 版本中更改。


这其实是有原因的。通过“每六个月发布一个新版本”的节奏,开发人员可以很快使用到新的语言功能。但是,在向 Java 永久添加语言功能之前,Java 团队会评估开发人员对此的评价。根据反馈的不同,可以在将预览功能添加到 Java SE 之前对其进行完善,也可以将其完全删除。


要体验预览语言功能,我们需要使用编译和运行时手动启用它们。这样可以确保我们不会意外使用预览功能。要使用文本块编译源文件,请使用 --enable-preview-release 13 选项。以下示例演示了如何使用命令行来编译源文件,例如对于 Java13.java 文件:


javac --enable-preview --release 13 Java13.java


为了加强预览功能可能会发生的变化,当我们执行前面的命令时,将会得到如下所示的编译器警告。


Note: Java13.java uses preview language features.Note: Recompile with Xlint:preview for details.


要执行类 Java13,我们需要使用 --enable-preview 选项:


java --enable-preview Java13


接下来,我们来看一下文本块的实现。


依然是字符串数据类型


传统的字符串和文本块都被编译为相同的类型:String。字节码类文件无法区分字符串值是从传统字符串还是文本块派生而来。这意味着文本块值存储在字符串池中。


考虑以下代码,你觉得变量 traditonalStringtextBlockString 引用相同的 String 实例吗?


String traditionalString = "Java";String textBlockString = """Java""";System.out.println(traditionalString == textBlockString);


答案是肯定的,因为它们的内容是完全相同的,所以上面的代码将会输出 true


在文章的开头,我讨论了使用传统的 String 处理多行字符串的繁琐,接下来,我们就来看看文本块在 Java 13 中如何提供便利?


轻松处理多行值


定义 JSON


开发人员经常使用多行字符串值,例如 JSON,HTML,XML 或正则表达式(regex)数据。通过文本块,使用多行 JSON 值的方法变得很简单。


String json = """    {      "name": "web",      "version": "1.0.0",      "dependencies": "AppA"    }""";


没有了转义字符和连接运算符,代码在视觉上显得很直观,因此,我们可以轻松编辑修改 JSON 值。不信?对比一下使用传统的 String 来定义 JSON 值:


String json =     "{" +      "\"name\": \"web\"," +      "\"version\": \"1.0.0\"," +      "\"dependencies\": \"AppA\" +     "}";


定义 SQL


有时候,我们需要将 SQL 查询语句存储为字符串。假如我们使用 String 变量存储了一个多行 SQL 查询语句,如下所示(对于 Java 12 或更早版本):


String query =   "SELECT name, age" +  "FROM EMP" +   "WHERE name = \'John\' +  "AND age > 20";


是不是觉得好像没毛病?其实是有问题的,它是一个无效的 SQL 查询语句。由于每行末尾都少了空格,这个查询语句会被解释为以下内容:


SELECT name, ageFROM EMPWHERE name = 'John'AND age > 20


要是使用文本块,就可以避免出现类似问题:


String query = """  SELECT name, age  FROM EMP  WHERE name = 'John'    AND age > 20  """;


定义正则表达式


正则表达式通常会包含许多特殊字符。在 Java 13 之前,我们将一个正则表达式写为 String 时,常常需要转义一些特殊字符,这使得我们难以编写、阅读或理解这些表达式。


这是一个在文本块之前存储正则表达式 [0-9]{3}\-[0-9]{4} 的示例:


String java12OrBeforeRegex = "[0-9]{3}\\t-[0-9]{4}";


有了文本块,我们可以定义出相同的正则表达式,如下所示:


String java13Regex = """[0-9]{3}\t-[0-9]{4}""";


文本块中的转义字符


我们可以将各种转义字符添加到文本块,就像将它们添加到 String 中一样。例如,可以通过将值放在多行上或使用转义字符(例如 \n)来在文本块中包含换行符。在以下代码中,I'mhappy 将会分别在两个行上。


String html = """<HTML>  <BODY>    <H1>I'm \nhappy</H1>  </BODY></HTML>""";


空格与缩进如何处理?


一个关键问题是如何处理文本块中附带的空白符。事实上,它由编译器很好地处理。在文本块中,任何行上最左边的非空白字符最左边的分隔符定义了字符串开始的位置。

在下图中,我们可以看到 getHTML() 方法返回了一个 String 类型的值,String 值的最左非空白字符以 < (<HTML> 中的 <)开头,该字符与结束定界符对齐


12.jpg


上面图中的这段代码,其实返回了下图所示的字符串(第一行 <HTML> 和最后一行 </HTML> 都不包含任何前导空格):


13.jpg


若要将字符串开头的空白字符标记为必需的(即:保留 <HTML> 左侧的空白符),我们需要向左移动分隔符或者任何非空白字符。


比如,我们将闭合定界符 """ 向左移动 8 个空格:


14.jpg


修改后的代码将会返回下图所示的 String 值,可以看到每行都添加了 8 个前导空格,外加用户额外缩进的空格。


15.jpg


默认情况下,文本块会删除每行末尾的空格。如果需要添加它们,可以使用八进制转义字符 \040(在 ASCII 中,空格为 32)来强制包含它们。

以下是一个示例,该示例在文本块第二行的末尾添加了一个空格:


String campaign = """            Don't leave home without -            money &\040            carry bag.            Reduce | Reuse            """;


注意,如果基本空格包含制表符 \t,则不会将其扩展,而是算作单个空格。


串联文本块


文本块可以与传统的字符串值通过 + 连接,以下是一个例子:


String concatenate() {    return """            Items to avoid -            Single            Use            Plastics            """             +             "Let's pledge to find alternatives";}


之所以提供这种方式,是因为我们有时候需要在字符串中插入变量的值:


String concatenate(Object obj) {    return """            Items to avoid -            Single            Use            """            + obj + """            Let's pledge to find             alternatives""";}


文本块可以当作字符串来使用,好处就是我们可以在文本块中使用 String 的方法。例如,我们可以使用 String.replace() 方法而无需做任何特殊处理:


String concatenateReplace(Object obj) {    return """        Items to avoid -        Single        Use        $type        Let's pledge to find        alternatives""".replace("$type", obj.toString());}


同样,我们可以使用 format() 方法或者 String 的任何其他方法。


总结


关于 Java 13 文本块的说明,这篇文章已经足够详细。文本块可以帮助我们开发人员轻松处理多行字符串值。需要记住,文本块目前只是一个预览功能,它随时可能更改。但即使以当前文本块的这种能力,它也必定会为我们节省很多的编码工作。


目录
相关文章
|
1月前
|
Java API Apache
Java编程如何读取Word文档里的Excel表格,并在保存文本内容时保留表格的样式?
【10月更文挑战第29天】Java编程如何读取Word文档里的Excel表格,并在保存文本内容时保留表格的样式?
124 5
|
8天前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
68 34
|
1月前
|
安全 Java 测试技术
🎉Java零基础:全面解析枚举的强大功能
【10月更文挑战第19天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
119 60
|
1月前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
30 2
|
2月前
|
Java 程序员
在Java编程中,关键字不仅是简单的词汇,更是赋予代码强大功能的“魔法咒语”。
【10月更文挑战第13天】在Java编程中,关键字不仅是简单的词汇,更是赋予代码强大功能的“魔法咒语”。本文介绍了Java关键字的基本概念及其重要性,并通过定义类和对象、控制流程、访问修饰符等示例,展示了关键字的实际应用。掌握这些关键字,是成为优秀Java程序员的基础。
26 3
|
2月前
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
65 2
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
|
2月前
|
Java 数据安全/隐私保护
Java ffmpeg 实现视频加文字/图片水印功能
【10月更文挑战第22天】在 Java 中使用 FFmpeg 实现视频加文字或图片水印功能,需先安装 FFmpeg 并添加依赖(如 JavaCV)。通过构建 FFmpeg 命令行参数,使用 `drawtext` 滤镜添加文字水印,或使用 `overlay` 滤镜添加图片水印。示例代码展示了如何使用 JavaCV 实现文字水印。
142 1
|
2月前
|
机器学习/深度学习 算法 Java
通过 Java Vector API 利用 SIMD 的强大功能
通过 Java Vector API 利用 SIMD 的强大功能
56 10
|
2月前
|
Oracle 安全 Java
Java 22 为开发人员带来了重大增强功能
Java 22 为开发人员带来了重大增强功能
45 9
|
2月前
|
Java
让星星⭐月亮告诉你,jdk1.8 Java函数式编程示例:Lambda函数/方法引用/4种内建函数式接口(功能性-/消费型/供给型/断言型)
本示例展示了Java中函数式接口的使用,包括自定义和内置的函数式接口。通过方法引用,实现对字符串操作如转换大写、数值转换等,并演示了Function、Consumer、Supplier及Predicate四种主要内置函数式接口的应用。
28 1