Java文本块

评论 0 浏览 0 2020-02-08

1.绪论

在之前的教程中,我们看到了如何在任何Java版本中使用多行字符串

在本教程中,我们将详细了解如何使用Java 15的文本块功能以最有效的方式声明多行字符串。

2.使用情况

从Java 15开始,文本块可以作为一个标准功能使用。对于Java 13和14,我们需要把它作为一个预视功能启用。

文本块以“””(三个双引号)开始,后面是可选的空白和换行。最简单的例子看起来是这样的:

String example = """
     Example text""";

请注意,文本块的结果类型仍然是String文本块只是为我们提供了另一种在源代码中书写String字面的方法。

在文本块中,我们可以自由使用换行符和引号,而不需要转义换行符。它允许我们以一种更优雅和可读的方式包含HTML、JSON、SQL或任何我们需要的文字片段。

在产生的字符串中,(基础)缩进和第一个换行不包括在内。我们将在下一节中看看缩进的处理方法。

3.缩进

幸运的是,在使用文本块时,我们仍然可以正确缩进我们的代码。为了实现这一点,一部分缩进被视为源代码,而另一部分缩进被视为文本块的一部分。为了做到这一点,编译器会检查所有非空行的最小缩进。接下来,编译器会将完整的文本块向左移动。

考虑到一个包含一些HTML的文本块:

public String getBlockOfHtml() {
    return """
            <html>

                <body>
                    <span>example text</span>
                </body>
            </html>""";
}

在这种情况下,最小缩进是12个空格。因此,<html>左边的所有12个空格以及所有后续的行都被删除。让我们来测试一下:

@Test
void givenAnOldStyleMultilineString_whenComparing_thenEqualsTextBlock() {
    String expected = "<html>\n"
      + "\n" 
      + "    <body>\n"
      + "        <span>example text</span>\n"
      + "    </body>\n"
      + "</html>";
    assertThat(subject.getBlockOfHtml()).isEqualTo(expected);
}

@Test
void givenAnOldStyleString_whenComparing_thenEqualsTextBlock() {
    String expected = "<html>\n\n    <body>\n        <span>example text</span>\n    </body>\n</html>";
    assertThat(subject.getBlockOfHtml())
       .isEqualTo(expected);
}

当我们需要明确的缩进时,我们可以对非空行(或最后一行)使用较少的缩进:

public String getNonStandardIndent() {
    return """
                Indent
            """;
}

@Test
void givenAnIndentedString_thenMatchesIndentedOldStyle() {
    assertThat(subject.getNonStandardIndent())
            .isEqualTo("    Indent\n");
}

此外,我们还可以在文本块内使用转义,我们将在下一节中看到。

4.转义

4.1.转移双引号

在文本块内,双引号不必被转义。我们甚至可以通过转义其中的一个,在我们的文本块中再次使用三个双引号:

public String getTextWithEscapes() {
    return """
            "fun" with
            whitespace
            and other escapes \"""
            """;
}

这是唯一必须转义双引号的情况。在其他情况下,这被认为是一种不好的做法。

4.2.转义行终止符

一般来说,换行符不必在文本块内转义。

然而,请注意,即使一个源文件有Windows行尾(\r\n),文本块也只会以换行(\n结束。如果我们需要回车(\r)出现,我们必须明确地将其添加到文本块中:

public String getTextWithCarriageReturns() {
return """
separated with\r
carriage returns""";
}

@Test
void givenATextWithCarriageReturns_thenItContainsBoth() {
assertThat(subject.getTextWithCarriageReturns())
.isEqualTo("separated with\r\ncarriage returns");
}

有时,我们的源代码中可能会有长长的几行文字,我们希望以可读的方式进行格式化。Java 14预览版增加了一个功能,使我们能够做到这一点。我们可以转义换行,使其被忽略

public String getIgnoredNewLines() {
    return """
            This is a long test which looks to \
            have a newline but actually does not""";
}

实际上这个String的字面意思只是等于一个正常的不间断的String

@Test
void givenAStringWithEscapedNewLines_thenTheResultHasNoNewLines() {
    String expected = "This is a long test which looks to have a newline but actually does not";
    assertThat(subject.getIgnoredNewLines())
            .isEqualTo(expected);
}

4.3.转义空格

编译器忽略了文本块中所有的尾部空格。然而,从Java 14预览版开始,我们可以使用新的转义序列\s来转义一个空格。编译器也会保留这个转义的空格前面的任何空格。

让我们来仔细看看转义空格的影响:

public String getEscapedSpaces() {
    return """
            line 1·······
            line 2·······\s
            """;
}

@Test
void givenAStringWithEscapesSpaces_thenTheResultHasLinesEndingWithSpaces() {
    String expected = "line 1\nline 2        \n";
    assertThat(subject.getEscapedSpaces())
            .isEqualTo(expected);
}

注意:上面的例子中的空格被替换为‘-'符号,以使其清晰可见。

编译器将删除第一行中的空格。然而,第二行是以转义的空格结束的,因此所有的空格都被保留了。

5.格式化

为了帮助变量替换,我们增加了一个新的方法,允许在一个字符串字面上直接调用String.format方法

public String getFormattedText(String parameter) {
    return """
            Some parameter: %s
            """.formatted(parameter);
}

6.结语

在这个简短的教程中,我们研究了Java的文本块功能。它可能不会改变游戏规则,但它能帮助我们写出更好、更可读的代码,这通常是一件好事。

像往常一样,文章的完整源代码可以在GitHub上获得。

最后更新2023-05-31
0 个评论