Java Text Blocks

Since Java 15, 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 three double-quote characters (""") as the opening and closing delimiters.
  • The opening three double-quote characters are always followed by a line terminator. 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. Watch out for Indentations

While text blocks have strict rules for the opening three double quotes, there is a lenient approach regarding the closing quotes. The closing quotes may appear in a new line or can be added at the end of the content. Remember, both are not the same thing. Placing the closing delimiter on the last line will append a new line to the final String.

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. Java text blocks remove all the incidental indentations and keep only 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 an 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.

3.2. Customize the Indentation

Let us imagine we want to give 2 tabs indentation to the 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 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 to 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. Using Text Blocks for Improved Readability

If a string is too long to accommodate the width of the editor/IDE, we can use it as a text block. The final String will still be a single-line literal.

5.1. Use Escape Sequence (‘\’)

Many times, we want to write the content into multiple lines in the program only, but they are single-string content. In this case, we can use an escape sequence single backslash '\'. It suppresses the inclusion of an implicit newline character.

For instance, we may want to have the following SQL string look like a text block (for readability purposes), but act as a single-line string literal (for being compact when we pass it to the database):

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

DO NOT add any whitespaces after ‘\‘ because you’ll get an error.

5.2. Use Escape Sequence (‘\s’)

If we do not want to strip the indentation for some reason, we can use '\s' (ASCII character 32, whitespace) 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", "."));

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 !!

Source Code on Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.