Learnitweb

Text Blocks in Java

1. Introduction

In Java, embedding a code snippet written in another language requires significant concatenation and escaping of characters. Here is such an example of HTML code embedded in Java.

String html = "<html>\n" +
              "    <body>\n" +
              "        <p>Hello, world</p>\n" +
              "    </body>\n" +
              "</html>\n";

Such type of code is difficult to read and maintain.

In Java, a text block is a multi-line string literal that simplifies writing strings that span multiple lines of code. A text block avoids the need of most escape sequences and automatically formats the string in a predictable way. Text blocks also allows developers to specify the format based on requirement.

Text blocks were introduced as preview feature in Java 13 and continued to be a preview feature in Java 14 as well. Based on the feedback in Java 14, text blocks were made permanent in Java 15.

You can think text block as a literal and can be used anywhere a string literal can be used in Java. The object produced from a text block is a java.lang.String with the same characteristics as a traditional double quoted string.

2. Syntax

A text block begins with three double-quote characters followed by a line terminator.

Continuing with our earlier example, here is the same string written with text block.

// With text block
String html = """
              <html>
                  <body>
                      <p>Hello, world</p>
                  </body>
              </html>
              """;

Following are examples of invalid text blocks:

// ERROR
String name = """Hello World""";

// ERROR
String name = """Hello 
				 World""";

Text blocks still allow you to manually provide white space and newline if that is the requirement providing more control. Text blocks do not directly support string interpolation. However, the String::formatted method helps in such cases. Text blocks do not support raw strings, that is, strings whose characters are not processed in any way.

A text block consists of zero or more content characters, enclosed by opening and closing delimiters. The opening delimiter is a sequence of three double quote characters (“””) followed by zero or more white spaces followed by a line terminator.

The content begins at the first character after the line terminator of the opening delimiter. The closing delimiter is a sequence of three double quote characters. The content ends at the last character before the first double quote of the closing delimiter.

3. Line terminators in text blocks

The content is allowed to have line terminators. The use of \n is allowed in a text block, but it is not necessary or recommended.

For example, the string literal

"line 1\nline 2\nline 3\n"

is same as

"line 1\n" +
"line 2\n" +
"line 3\n"

and is same as the text block

"""
line 1
line 2
line 3
"""

Note that it is legal to use ” and “” freely inside a text block, except immediately before the closing delimiter. However, if a sequence contains three consecutive ” characters, at least one of them must be escaped to prevent it from being mistaken for the closing delimiter.

4. Compile-time processing

The Java compiler processes the content of a text block in three distinct steps:

  • Line terminators in the content are translated to LF (\u000A). This ensures that the string derived from the content is equivalent across platforms, even if the source code has been translated to a platform encoding.
  • Any incidental whitespace around the content, added to align with the indentation of the Java source code, is removed. Incidental whitespace is the spaces added to indent the embedded string so that it looks better. Here, dots are used to represent the incidental spaces.
String html = """
..............<html>
..............    <body>
..............        <p>Hello, world</p>
..............    </body>
..............</html>
..............""";

Whitespace can also appear at the end of each line. Here is such an example with dots used to represent the whitespace:

String html = """
..............<html>...
..............    <body>
..............        <p>Hello, world</p>....
..............    </body>.
..............</html>...
..............""";

Same amount of white space is removed from each line of content until at least one of the lines has a non-white space character in the leftmost position. The position of the opening “”” characters has no effect, but the position of the closing “”” characters does have an effect if placed on its own line.

To include some indentation in the string’s contents, invoke the indent method on the text block:

String colors = """
    Hello
    World""".indent(4);

A text block can avoid incidental whitespace stripping by placing the closing delimiter at the beginning of a source line:

String html = """
                  <html>
                      <body>
                          <p>Hello World.</p>
                      </body>
                  </html>
""";

  • Escape sequences within the content are interpreted. By performing this interpretation as the final step, developers can include escape sequences like \n without them being altered or removed during earlier processing stages. Text blocks support all of the escape sequences supported in string literals, including \n, \t, \’, \”, and \.

The processed content is stored in the class file as a CONSTANT_String_info entry in the constant pool, similar to the characters of a string literal. The class file does not indicate whether a CONSTANT_String_info entry originated from a text block or a string literal. At runtime, a text block evaluates to an instance of String, just as a string literal does. Due to interning, two text blocks with identical processed content will reference the same String instance, just as string literals do.

5. Escape sequences

The \ escape sequence explicitly suppresses the insertion of a newline character.

String text = """
                This is a hello world \
                message with escape \
                line terminator \
                """;
System.out.println(text);

Output

This is a hello world message with escape line terminator

The new \s escape sequence simply translates to a single space (\u0020).

Escape sequences are not translated until after incidental whitespace is removed, so \s can be used as a barrier to prevent the stripping of trailing whitespace.

        String text = """
                This is a hello world \s
                message with escape \s
                line terminator \s
                """;
        System.out.println(text);

Output

This is a hello world  
message with escape  
line terminator

There are exact two spaces after each line.

6. equals and == with text blocks

The object produced from a text block is a java.lang.String with the same characteristics as a traditional double quoted string.

        String message1 = """
                hello
                world
                """;
        String message2 = """
                hello
                world
                """;
        System.out.println(message1 == message2);   //true
        System.out.println(message1.equals(message2)); //true

7. Text blocks as method argument

Text blocks may be used as a method argument:

System.out.println("""
    Hello
    World
    """);

8. Normalization of line terminators

One challenge with multi-line string literals is the variation in line terminators (\n, \r, or \r\n) across different platforms. Text editors on various platforms may subtly alter these line terminators, and if a source file is edited on multiple platforms, a text block might end up with a mix of different line terminators. This can lead to confusing and inconsistent results.
To avoid these problems, the Java compiler normalizes all line terminators in a text block to be \n, regardless of what line terminators actually appear in the source file.

9. Some important methods

public String formatted(Object… args)Formats using this string as the format string, and the supplied arguments. This method is equivalent to String.format(this, args).
public String stripIndent()Returns a string whose value is this string, with incidental white space removed from the beginning and end of every line.
public String translateEscapes()Returns a string whose value is this string, with escape sequences translated as if in a string literal.

10. Conclusion

Text blocks in Java provide a powerful and convenient way to handle multi-line strings, offering improved readability and ease of use compared to traditional string literals. By simplifying the inclusion of large, structured data such as JSON, XML, and SQL directly within your code, text blocks reduce the need for cumbersome string concatenation and escaping of special characters.

Key features such as automatic indentation management, consistent line terminator normalization, and support for escape sequences make text blocks a valuable addition to any Java developer’s toolkit. As you integrate text blocks into your projects, you’ll find your code cleaner, more maintainable, and easier to read.

With these advantages, text blocks enhance your ability to write robust and efficient Java applications, paving the way for more effective coding practices and better overall software design.