Java Text Blocks – Java文本块

最后修改: 2020年 2月 8日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

In a previous tutorial, we saw how we can use multi-line strings in any Java version.

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

In this tutorial, we’ll see in detail how to use the Java 15 text blocks feature to declare multi-line strings most efficiently.

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

2. Usage

2.使用情况

Since Java 15, text blocks are available as a standard feature. With Java 13 and 14, we needed to enable it as a preview feature.

自Java 15以来,文本块作为一项标准功能可用。对于Java 13和14,我们需要将其作为预检功能来启用。

Text blocks start with a “”” (three double-quote marks) followed by optional whitespaces and a newline. The most simple example looks like this:

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

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

Note that the result type of a text block is still a String. Text blocks just provide us with another way to write String literals in our source code.

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

Inside the text blocks, we can freely use newlines and quotes without the need for escaping line breaks. It allows us to include literal fragments of HTML, JSON, SQL, or whatever we need, in a more elegant and readable way.

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

In the resulting String, the (base) indentation and the first newline are not included. We’ll take a look at the handing of indentation in the next section.

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

3. Indentation

3.缩进

Luckily, when using text blocks, we can still indent our code properly. To achieve that, part of the indentation is treated as the source code while another part of the indentation is seen as a part of the text block. To make this work, the compiler checks for the minimum indentation in all non-empty lines. Next, the compiler shifts the complete text block to the left.

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

Consider a text block containing some HTML:

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

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

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

In this case, the minimum indentation is 12 spaces. Thus, all 12 spaces to the left of <html> and on all subsequent lines are removed. Let’s test this:

在这种情况下,最小缩进是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);
}

When we need explicit indentation, we can use less indentation for a non-empty line (or the last line):

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

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

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

Moreover, we can also use escaping inside text blocks, as we’ll see in the next section.

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

4. Escaping

4.逃亡

4.1. Escaping Double-Quotes

4.1.转移双引号

Inside text blocks, double-quotes don’t have to be escaped. We could even use three double-quotes again in our text block by escaping one of them:

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

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

This is the only case where double-quotes must be escaped. In the other cases, it’s considered a bad practice.

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

4.2. Escaping Line Terminators

逃离生产线的终结者

In general, newlines don’t have to be escaped inside text blocks.

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

However, note that even if a source file has Windows line endings (\r\n), the text blocks will only be terminated with newlines (\n). If we need carriage returns (\r) to be present, we have to explicitly add them to the text block:

然而,请注意,即使一个源文件有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");
}

Sometimes, we might have long lines of text in our source code that we want to format in a readable way. Java 14 preview added a feature that allows us to do this. We can escape a newline so that it is ignored:

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

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

Actually this String literal will just equal a normal non-interrupted String:

事实上,这个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. Escaping Spaces

4.3.逃逸空间

The compiler ignores all trailing spaces in text blocks. However, since Java 14 preview, we can escape a space using the new escape sequence \s. The compiler will also preserve any spaces in front of this escaped space.

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

Let’s take a closer look at the impact of an escaped space:

让我们仔细看看逃逸空间的影响。

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);
}

Note: the spaces in the example above are replaced with the ‘·’ symbol to make them visible.

注意:上面的例子中的空格被替换成’-‘符号,使其可见。

The compiler will remove the spaces from the first line. However, the second line is terminated with an escaped space, and all the spaces are thus preserved.

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

5. Formatting

5.格式化

To aid with variable substitution, a new method was added that allows calling the String.format method directly on a String literal:

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

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

6. Conclusion

6.结语

In this short tutorial, we looked at the Java Text Blocks feature. It may not be a game-changer, but it helps us to write better and more readable code, which is generally a good thing.

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

As always, the full source code of the article is available over on GitHub.

一如既往,该文章的完整源代码可在GitHub上获得