0%

Java语言新特性漫谈:Java 13篇

本文是《Java语言新特性漫谈》系列文章中的一篇,该系列文章主要探讨各 Java 版本的语言特性方面的增强更新。

文本块(预览特性)

在 Java 13 之前,对多行字符串的支持并不友好:不仅需要拼接,还需要显式地插入转义形式的行终结符,甚至如果涉及双引号、TAB 等特殊字符时也要使用转义。

因此,Java 13 引入了“文本块”,用以优化对多行字符串的支持。

1
2
3
4
5
6
7
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";

如上所示,文本块使用“三个双引号”(下文简称“三引号”)界定。

起始三引号后应跟行终结符。因此,文本块不可能写作一行,这是符合其设计目标的——支持多行字符串。

虽然起始的三引号与行终结符间可以插入空格以及其他一些空白字符,但这通常没有实质意义。
文本块在其他语句中也常使用“三引号”,比如:Python、PowerShell 等等。

结束三引号可以紧跟在最后一行文本之后,或者新起一行。但两者是有区别的,前者是以正常文本结尾,后者是以换行结尾的。

文本块的换行符是规范化的,无论在什么平台都是 \n。如果需要平台化,可以使用 String.replaceAll("\n", System.lineSeparator())

文本块也支持普通字符串中的各种转义字符,但是通常转义字符是非必要的,直接使用原字符通常是可行的。比如:双引号、TAB 等等。

大多数情况下,应该只有三引号才必须转义——只需转义首个双引号——不过平时几乎也不太会用到三引号。

文本块的语法大都很简单,唯一值得讨论的是其缩进规则。

可以想见,由于代码需要缩进格式化,所以不可能保留文本块中所有行的前缀缩进,并且不能在代码格式化后影响原缩进。

因此,文本块中每行的缩进具有自动移除的特性,编译器会查找缩进最少的行,然后对每一行文本移除该缩进量。即是一种“相对缩进”的概念。
而起始三引号行不会参与缩进的计算,这是为了简化缩进规则;但是,结束三引号行会。一个排版技巧是使用结束三引号来调整缩进。

1
2
3
4
String indentedByToSpaces = """
First line
Second line
""";

如上代码,结束的三引号缩进与其他行不一致,且为最少缩进,所以自动移除缩进以它为准——这使得文本保留了部分缩进。

不过,很显然这个技巧只适用于以新行结尾的文本块。否则,只好使用 String 类新增的缩进相关方法来处理。

String 类为文本块添加的方法支持,包括 formatted(Object ...args)stripIndent()translateEscapes() 等。

另外,需要注意的是,尽量不要混合使用空格和 TAB 来进行缩进,编译器会同等对待两者,即一个空格等价于一个 TAB。
而由于在不同的编辑器中,一个 TAB 显示为 4 个或 8 个空格,因此可能得到意外的缩进效果。

可以通过 -Xlint:text-blocks 来检查是否存在混用。如果存在,则编译时会输出警告 inconsistent white space indentation

除了会移除缩进外,编译器也会移除每行结尾的空白字符。

Switch表达式(预览特性)

这是关于“Switch 表达式特性”自 Java 12 后的第二个预览版。基本上没有太大区别,唯一一点调整是:不再使用 break 为表达式返回值,而改用 yield 关键字了。

关于预览特性的启用

1
2
3
4
5
6
7
# 编译并执行
javac --enable-preview --release 13 -d classes MyApp.java
java --enable-preview -cp classes MyApp
# 启动 JShell
jshell --enable-preview
# 直接编译执行独立源文件
javac --enable-preview --release 13 MyApp.java

参考

Oracle - Programmer’s Guide To Text Blocks

Programmer’s Guide To Text Blocks

Definitive Guide To Text Blocks In Java 13

Java Text Blocks