In this week’s post we’re going to look at Java text blocks, which were a preview language feature in JDK 13 and JDK 14.
A preview feature is a new feature of either the Java language, the JVM or the JSE API. The feature is fully specified and implemented, but might not become permanent. That said, most of the important preview features have become permanent in later Java versions. Text blocks became permanent in Java 15. We probably won’t ever use Java 15 directly because Java 17 is currently available, and is a LTS (long term support) release.
What is a Java Text Block?
A text block is a multi-line string literal that doesn’t require us to use escape sequences such as \n
, \"
, etc. The compiler automatically formats the string literal and gives us additional control over this formatting if needed.
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 space characters followed by a line terminator. The actual string content begins at the first character after the line terminator of the opening delimiter. - The closing delimiter is also a sequence of three double quote characters (
"""
). The string content ends at the last character before the first double quote of the closing delimiter.
Improving Text Readability
As a first example of text blocks, let’s see how they can improve the readability of embedded XML, HTML, JSON or SQL.
We know that we have to use escape sequences to insert special characters into string literals, such as newlines and carriage returns, as well as escaping double quotes.
Here’s an HTML example:
String html = "<!DOCTYPE html>" + "<html>\n" + " <head>\n" + " <title>Hello World</title>\n" + " </head>\n" + " <body>\n" + " <p>Hello, world!</p>\n" + " </body>\n" + "</html>\n";
We can now replace the multiple string literals, escape sequences and string concatenation operators with a text block:
String html = """ <!DOCTYPE html> <html> <head> <title>Hello World</title> </head> <body> <p>Hello, world!</p> </body> </html> """;
Here’s a longer XML example:
String deploymentDescriptor = "<web-app xmlns=\"http://xmlns.jcp.org/xml/ns/javaee\"\n" + "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" + "xsi:schemaLocation=\"http://xmlns.jcp.org/xml/ns/javaee\n" + "http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd\"\n" + "version=\"3.1\">\n" + "<servlet>\n" + "<servlet-name>Hello</servlet-name>\n" + "<servlet-class>com.incusdata.HelloServlet</servlet-class>\n" + "</servlet>\n" + "<servlet-mapping>\n" + "<servlet-name>hello</servlet-name>\n" + "<url-pattern>/*</url-pattern>\n" + "</servlet-mapping>\n" + "</web-app>\n" ;
What a mission to insert all the escape characters properly! It becomes so much simpler with text blocks:
String deploymentDescriptor = """ <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>Hello</servlet-name> <servlet-class>com.incusdata.HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>hello</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app> """;
So we can just imagine how simple it would be to embed JSON in a Java text block!
Delimiter Placement
The opening """
delimiter *must* be followed by any amount of white space and then a line terminator.
The closing """
delimiter can be on a separate line as in the two examples, or on the same line as the last character of the string content.
What’s really nice is that the leading white space before each line of the content is removed automatically, because the compiler assumes that we were probably using it for improving the readability of our code. The compiler will count the number of leading white space characters on each line. The minimum number is the amount of white space it will remove from each line. This is regarded as the incidental white space. The essential white space such as the actual HTML or XML indentation we’ve used will be kept.
The easiest rule of thumb to follow is to place both """
delimiters on their own lines (as in the examples) and place the closing delimiter in the same column as the opening delimiter.
What’s Next?
There are a number of rules regarding leading and trailing spaces in text blocks. There are also some new String
methods that we can use to customise the indentation, concatenation and escape characters. We’ll look at those in another post.
For more information about text blocks, see JEP 378: Text Blocks.
As always, please share your comments and questions.