1. Introduction
When dealing with regular strings and aiming to create multiline strings, you must explicitly include the line terminator (\n). This approach not only adds extra work but also produces a string that isn’t very readable. The Text Block is the ideal solution to this limitation, providing a simplified approach to multiline string management. In this article, you’ll discover Text Blocks and learn how to use them in your Java programs.
2. Text Block Syntax
Text blocks were introduced in Java 15 by the JDK Enhancement Proposal(JEP) 378. Before starting, you should know that a text block is not another Java type. A text block is just a simple way of creating a String that spans multiple lines. You can create a text block with the following syntax:
String query = """
Select *
From
Students
Where Language = 'Java';
""";
Running the line above in JShell will display the following:
query ==> "Select *\n From\n Students\n Where Language = 'Java';\n"
As you can see the line feed character \n is added automatically to the resulting String.
Note that the line containing the opening delimiter “”” must only have whitespace characters. The following code will not compile:
String badQuery = """ //this line will not compile
Select *
From
Students
Where Language = 'Java';
""";
Also, note that the closing delimiter can be on the same line as the last character of the String.
String query = """
Select *
From
Students
Where Language = 'Java'; """;
This prevents the text block from adding an extra line at the end of the string.
query ==> "Select *\n From\n Students\n Where Language = 'Java';"
3. Escaping The Line Terminator
As seen above, the line feed character \n is automatically added to the resulting String by default. If you don’t want it, then you should use the backslash ( \ ) to escape the line terminator in this way:
String query = """
Select * \
From \
Students \
Where Language = 'Java';\
""";
Which gives the following output in JShell:
query ==> "Select * From Students Where Language = 'Java';"
4. Escaping The Text Block delimiter “””
In Text Blocks, double quotes (“) are treated as regular characters, unlike in classic Strings. You can use them normally in your text content as long as there are not three in a row (“””). If you still wish to insert three double quotes in a row, you must escape them with a backslash ( \ ).
String correctTextBlock = """
I am a text block
with 3 double-quotes in a row \"""
But it's Ok because it is escaped
This line has only 2 double-quotes "" no need to escape
""";
5. Keeping Trailing Whitespaces in a Text Block
By default, the Java Compiler removes any trailing whitespace (incidental whitespace) from each line of a text block and normalizes the line terminator. If you need to retain trailing whitespaces for any reason, use the \s escape sequence. This capability exists because the translation of escape sequences occurs during the final step of text block processing by the Java compiler. So using an escape sequence has the effect of bypassing the whitespace stripping.
String retainTrailingWhitespace = """
without escape sequence
with escape sequence \s
Check the difference
""";
retainTrailingWhitespace ==> "without escape sequence\nwith escape sequence \nCheck the difference\n"
As you can see any trailing whitespace before the \s escape sequence is retained.
6. Incidental Whitespaces
6.1. What is an incidental whitespace?
During the compilation process, the Java Compiler automatically removes what it considers to be incidental whitespaces from each line of a text block. Incidental whitespaces are whitespaces which are not part of the text content. The compiler assumes that the developer may have added them for indentation purposes.
To determine the number of blank characters to remove per line, the compiler initially identifies the leftmost line. The leftmost line is the one with the leftmost non-blank character. If the closing delimiter is on its line, it is considered while looking for the leftmost-justified line.
Hence, the algorithm involves traversing each line and removing all preceding blank characters up to the position of the leftmost character. The detailed algorithm can be found on the JEP 378. The Java compiler treats trailing whitespaces as incidental and eliminates them by default unless an escape sequence like \s is utilized, as demonstrated earlier.
In the following examples, we consider a text block, where we use “.” to illustrate a whitespace and “|” to illustrate the line limit to the left. We are not showing the opening delimiter “”” since it doesn’t count when determining the incidental whitespaces. We focus only on incidental whitespaces at the beginning of the line.
6.2. Incidental Whitespaces: Example 1
In this example, the first line has 3 whitespaces and the three other lines have eight. This makes the line with “Java” the leftmost-justified one.
Before
|...Java
|........Text
|........Block
|........"""
After Incidental whitespace removal
|Java
|.....Text
|.....Block
|....."""
6.3. Incidental Whitespaces: Example 2
The line with “Text” is the leftmost-justified one with three whitespaces.
Before
|........Java
|...Text
|........Block
|........"""
After Incidental whitespace removal
|.....Java
|Text
|.....Block
|....."""
6.4. Incidental Whitespaces: Example 3
Similarly to the previous examples, the line containing “Block” is the leftmost-justified.
Before
|........Java
|........Text
|...Block
|........"""
After Incidental whitespace removal
|.....Java
|.....Text
|Block
|....."""
6.5. Incidental Whitespaces: Example 4
In this example, the line which contains only the closing delimiter is the leftmost-justified.
Before
|........Java
|........Text
|........Block
|..."""
After Incidental whitespace removal
|.....Java
|.....Text
|.....Block
|"""
6.6. Incidental Whitespaces: Example 5
Since the closing delimiter isn’t on a new line, the text block contains only three lines, all of which are left-justified in the same way.
Before
|........Java
|........Text
|........Block"""
After Incidental whitespace removal
|Java
|Text
|Block"""
7. New Methods to Handle Text Blocks
With the advent of text blocks in Java 15, Java introduced some new methods.
7.1. formatted(Object… args)
This method is the equivalent of the String.format(this, args)
method for text blocks.
String formattedQuery = """
Select *
From
%s
Where %s = '%s';
""".formatted("Students ","Language","Java");
Output
formattedQuery ==> "Select *\n From\n Students \nWhere Language = 'Java';\n"
7.2. String stripIndent()
This method removes all incidental whitespaces using the same algorithm as the compiler (see examples above). This approach can be helpful if you need to strip multiline text passed as an input parameter to one of your methods before processing it further.
7.3. String translateEscapes()
The method translates all the escape sequences(\b, \f, \n, \t, \r, \”, \’, \ and octal escapes) from text block and string literals. Translation here means to replace the escape sequence with the actual character.
8. Conclusion
In this article, you discovered Java Text Blocks and the features they provide for creating multiline strings. To learn more useful tips on String manipulation, check out this article about String manipulation for Technical Interviews.
9. References
1) OCP Oracle Certified Professional Java SE 17 by Khalil A. Mughal and Vasily A. Strelnikov
2) Oracle Java Documentation