In Java, a text block is a multi-line string literal. It means we do not need to get into the mess of explicit line terminators, string concatenations, and delimiters otherwise used for writing normal string literals.
Java text blocks were included in Java 13 (JEP 355) and Java 14 (JEP 368) as preview features. It has become a standard feature in Java 15 (JEP 378).
1. Text Block Syntax
- Text blocks comprise multiple lines of text and use three double-quote characters (
"""
) as the opening and closing delimiters. - The opening three double-quote characters are always followed by a line terminator.
- We cannot have the delimiters and text blocks on a single line. The opening delimiter must be on its own line. Content has to start on the next line only.
- If the text content contains single or double quotes, there is no need to escape them.
String dbSchema = """
CREATE TABLE 'TEST'.'EMPLOYEE'
(
'ID' INT NOT NULL DEFAULT 0 ,
'FIRST_NAME' VARCHAR(100) NOT NULL ,
'LAST_NAME' VARCHAR(100) NULL ,
'STAT_CD' TINYINT NOT NULL DEFAULT 0
);
""";
While the above text block looks very simple, still a lot of things happen under the hood. Let’s explore.
2. Text Blocks are Java Strings
- The instance produced from a text block is of type
java.lang.String
with the same characteristics as a traditional double-quoted string. This includes object representation and interning into string pool. - We can use text blocks to pass as method arguments of type
String
. - Text blocks can be used anywhere a string literal can be used. For example, we can use it for string concatenation.
String string = "Hello";
String textBlock = """
World""";
String joinedString = string + textBlock;
System.out.println(joinedString);
Program output:
Hello
World
3. Indentation
3.1. Incidental and Essential Indentations
The text blocks preserve the indentation of its content. To perform this, JEP divides the space into incidental and essential indentations.
To talk in context, let us refer to the first example.
String dbSchema = """
CREATE TABLE 'TEST'.'EMPLOYEE'
(
'ID' INT NOT NULL DEFAULT 0 ,
'FIRST_NAME' VARCHAR(100) NOT NULL ,
'LAST_NAME' VARCHAR(100) NULL ,
'STAT_CD' TINYINT NOT NULL DEFAULT 0
);
""";
System.out.println(dbSchema);
Program output:
|CREATE TABLE 'TEST'.'EMPLOYEE'
|(
| 'ID' INT NOT NULL DEFAULT 0 ,
| 'FIRST_NAME' VARCHAR(100) NOT NULL ,
| 'LAST_NAME' VARCHAR(100) NULL ,
| 'STAT_CD' TINYINT NOT NULL DEFAULT 0
|);
Here, we have the indentations of two types:
- The first indentation is from the start of the line till the word
"CREATE"
in all the lines. This can increase or decrease based on various factors such as formatting plugins or the developer’s choice. It is incidental indentation. - The second indentation is from the start of character
'('
till'ID'
. It is most of the time 4 or 8 spaces long. This should be honored to maintain the intent of indentation of text block. This is called essential indentation.
Java text blocks remove all the incidental indentations and keep only essential indentations.
3.2. Customize the Indentation
Let us imagine we want to give 2 tabs indentation to left for all the lines in the above example. We can do this by carefully positioning the closing triple quotes to move exactly 2 tabs to the left. Put it at the exactly same place from where the essential indentation should pick up.
String dbSchema = """
CREATE TABLE 'TEST'.'EMPLOYEE'
(
'ID' INT NOT NULL DEFAULT 0 ,
'FIRST_NAME' VARCHAR(100) NOT NULL ,
'LAST_NAME' VARCHAR(100) NULL ,
'STAT_CD' TINYINT NOT NULL DEFAULT 0
);
""";
System.out.println(dbSchema);
Program output:
| CREATE TABLE 'TEST'.'EMPLOYEE'
| (
| 'ID' INT NOT NULL DEFAULT 0 ,
| 'FIRST_NAME' VARCHAR(100) NOT NULL ,
| 'LAST_NAME' VARCHAR(100) NULL ,
| 'STAT_CD' TINYINT NOT NULL DEFAULT 0
| );
Also, note that trailing white space on each line in a text block is also stripped away by the Java compiler.
3.3. Handling Tabs
Unfortunately, it is not difficult for the compiler to know how TAB characters are displayed in different editors.
Therefore, the compiler treats a single space character the same as a single TAB character, even though the TAB character might result in white space equivalent upto eight spaces.
4. Line Terminator
Different platforms have different line terminator characters. Java does not get into platform detection and normalizes all line terminators in a text block to be \n
.
If the platform line terminator is required then String::replaceAll("\n", System.lineSeparator())
can be used.
String string = "Hello";
String textBlock = """
World""";
String joinedString = string + textBlock;
joinedString = joinedString.replaceAll("\n", System.lineSeparator());
System.out.println(joinedString);
5. New Escape Sequences
5.1. Escape Line-Terminator
Many times, we want to write the content into multiple lines in the program only, but they are actually a single-string content. In this case we can use line-terminator escape character which is single backslash '\'
. It suppresses the inclusion of an implicit newline character.
String dbSchema = """
CREATE TABLE 'TEST'.'EMPLOYEE'\
(\
'ID' INT NOT NULL DEFAULT 0 ,\
'FIRST_NAME' VARCHAR(100) NOT NULL ,
'LAST_NAME' VARCHAR(100) NULL ,\
'STAT_CD' TINYINT NOT NULL DEFAULT 0 \
);
""";
System.out.println(dbSchema);
Program output:
|CREATE TABLE 'TEST'.'EMPLOYEE'('ID' INT NOT NULL DEFAULT 0 ,'FIRST_NAME' VARCHAR(100) NOT NULL ,
'LAST_NAME' VARCHAR(100) NULL ,'STAT_CD' TINYINT NOT NULL DEFAULT 0 );
5.2. Escape Incident Space stripping to the Right
If we do not want to strip the indentation for some reason, we can use '\s'
(ASCII character 32, white space) escape sequence. Using it at the end of any line guarantees that the line will have all space characters till '\s'
is encountered.
String dbSchema = """
CREATE TABLE 'TEST'.'EMPLOYEE' \s
( \s
'ID' INT NOT NULL DEFAULT 0 , \s
'FIRST_NAME' VARCHAR(100) NOT NULL , \s
'LAST_NAME' VARCHAR(100) NULL , \s
'STAT_CD' TINYINT NOT NULL DEFAULT 0 \s
); \s
""";
System.out.println(dbSchema.replaceAll("\s", "."));
Program output. In this program output, I have replaced all the space characters with dot '.'
to make you understand its effect.
CREATE.TABLE.'TEST'.'EMPLOYEE'...........
(........................................
..'ID'.INT.NOT.NULL.DEFAULT.0.,..........
...'FIRST_NAME'.VARCHAR(100).NOT.NULL.,..
..'LAST_NAME'.VARCHAR(100).NULL.,........
..'STAT_CD'.TINYINT.NOT.NULL.DEFAULT.0...
);.......................................
6. Best Practices
- Only use a text block when it improves the clarity of the code, particularly with multi-line strings.
- If a string fits in the usecase, always prefer to use strings. They are better for application performance.
- To maintain the desired indentation, always use the position of closing triple quotes relative to the position of the last line on the content.
- Avoid in-line text blocks within complex expressions such as lambda expressions or stream operations to maintain readability. Consider refactoring to a local variable or to a static final field.
- Either use only spaces or only tabs for the indentation of a text block. Mixing white space will lead to a result with irregular indentation.
Drop me your questions in the comments.
Happy Learning !!