语法话题空白符疑惑语法解析空白的转义
语法话题
本期的语法话题为:
文本块是怎样处理空白符的?
在之前的话题《【Java语法解析】Java 15中,文本块有哪些优势?》中,我们介绍了文本块的基本语法,以及文本块的优势所在。这次,我们来解释下,文本块对空白符的处理细节。
空白符疑惑
在声明文本块时,文本块的空白符,可能会给我们带来一丝困扰。因为空白符不可见,为了能够清晰表示空白符,下面程序中,空格使用“*”表示。当然,我们也可以使用其他的空白符(制表符与换页符)。
package test;
public class Test {
public static void main(String[] args) {
String content = """
**a**
**
***c
*""";
System.out.print(content);
}
}
程序运行结果如下(空格用“*”表示):
*a **c
文本块包含4行内容(第6 ~ 9行),其中,第6,8与9行删除了行首的一个空格,同时第6行末尾的两个空格也得到删除,第7行删除了行首的两个空格,该如何解释这个结果呢?
语法解析
文本块对空白符的处理如下:
首先,会提取文本块中的每一行(不包括行分隔符),对于每一个非空白行(该行不都是空白符)与最后一行(不管是否为空白行),分别计算这些行的行首空白符个数,记录最小的空白符个数值(设为n)。n可以看做是文本块内所有行向左平移的基准。对于每一个非空白行,行首删除n个空白符(步骤1计算的最小值),行尾删除所有空白符。对于每一个空白行,使用空字符串代替(行分隔符会保留)。
有了这样的处理过程,我们就可以来解释之前的程序:
提取文本块中的每一行,分别计算第6,8与9行的行首空白符个数。
第7行为空白行,不予计算。第9行虽然也是空白行,但属于最后一行,依然计算。 经过计算,这3行中,行首最小空白符个数为1。
第6行,行首2个空白符。第8行,行首3个空白符。第9行,行首1个空白符。 对于非空白行(第6行与第8行),删除行首的1个空白符与行末的所有空白符。对于空白行(第7行与第9行),使用空字符串代替。
空白的转义
既然文本块会处理相关的空白符,那我们自然就会想到一点:如果我们原意就是要保留一定数量的空白符(例如保留行末的空格),那该如何处理?很简单,我们可以使用转义序列。
在文本块处理空白符的时候,会首先完成之前介绍的处理过程,然后才会解析转义序列。也就是说,在删除空白符的时候,空白符的转义序列尚未解析,因此,使用转义序列是可以保留空白符的。同时,从Java 15起,转义序列又增加了一个新的转义字符——s,用来对空格转义(主要用于文本块中)。
package test;
public class Test {
public static void main(String[] args) {
String content = """
*ab*s*""";
System.out.print(content);
}
}
程序运行结果如下(空格用“*”表示):
ab**
由结果可知,编译器会删除行首的字符,而从行末的角度看,存在3个空格(“s”也是空格),不过,编译器这次只将“s”后面的空格删除,而“ab”与“s”之间的空格,“s”(转义的空格)是没有删除的。



