First demo of String Templates with Java 21
Java 21 was released a few days ago, and today, I had some free time to try out the new String Templates feature described in the JEP-430. In this article, I provide a simple demonstrative example of a custom string template processor so that you can better understand the usefulness of this new feature.
Introduction
First, I suggest you read the JEP-430, which is very readable and not particularly complex. You should read at least the first half part since it is more straightforward than the second.
The new feature allows you to write something like the following:
String userName = //....
int birthYear = //....
String info = STR."User \{userName} was born in \{birthYear}.";
The above string is easier to write and understand than the classic string concatenation:
String info = "User " + userName + " was born in " + birthYear + ".";
The interpolation of string templates is performed by an implementation of the StringTemplate.Processor
interface, which is specifically a functional interface. In Java 21, the Platform provides three predefined processor implementations: STR
, RAW
, and FMT
. Only STR
is implicitly imported into every Java compilation unit. The other two processors must be explicitly imported using the following “static” import statements:
import static java.lang.StringTemplate.RAW;
import static java.util.FormatProcessor.FMT;
You can also implement your string template processor besides the three default implementations. And here, you can glimpse the true potential of this new feature. Think about, for example, the interpolation of a JDBC query string. A bare, minimal example of this is provided at the end of the JEP-430 document.
Remember that at this moment, as of Java 21, String Templates is a preview feature. It means that it is not yet permanent and may be modified, improved, or (in the worst case) removed in future Java versions. If you want to use String Templates and are compiling using the javac
tool directly, you must also specify the --enable-preview option
, as you will see below.
A simple demonstrative “quoting” processor
To show the usefulness of String Templates, consider the following scenario. Suppose you want to develop a simple processor that interpolates the values in the following ways:
- A
null
value is interpolated as<null>
. - A string (anything that is a
CharSequence
) is interpolated as"something"
, quoted using the double quote ASCII character. - Any other object is represented as a string in the standard way, according to its
toString()
method.
The following is the source code of the QuotingProcessor
:
import java.lang.StringTemplate.Processor;
public class QuotingProcessor implements Processor<String, RuntimeException> {
@Override
public String process(StringTemplate st) {
var sb = new StringBuilder();
var fragItr = st.fragments().iterator();
for (var value : st.values()) {
sb.append(fragItr.next()); // appends previous fragment
if (value == null) {
sb.append("<null>");
} else if (value instanceof CharSequence) {
sb.append('"').append(value).append('"');
} else {
sb.append(value);
}
}
sb.append(fragItr.next()); // appends last fragment
return sb.toString();
}
}
As you can see, I also used the new “var syntax” introduced in Java 10. If you are unaware or not acquainted with this feature, please use the type StringBuilder
for sb
, Iterator<String>
for fragItr
, and Object
for value
. Furthermore, I have not used packages just for simplicity (feel free to use them if you prefer).
To compile the QuotingProcessor.java
file using the javac
tool, you need to run the following command:
javac --enable-preview -source 21 QuotingProcessor.java
Note that -source
is also required to use the --enable-preview
option. Now, you can write a very trivial Sample
class to test the processor:
import java.lang.StringTemplate.Processor;
public class Sample {
public static final Processor<String, RuntimeException> QS = new QuotingProcessor();
public static void main(String[] args) {
String firstName = "Jane";
String lastName = null;
int birthYear = 1967;
System.out.println(QS."first name: \{firstName}; last name: \{lastName}; birth year: \{birthYear}");
}
}
To compile the Sample.java
file using the javac
tool, you need to run the following command:
javac --enable-preview -source 21 Sample.java
If compilation is successful, you can run the Sample
class using the command:
java --enable-preview Sample
The output is:
first name: "Jane"; last name: <null>; birth year: 1967
Final note: if I had used packages, I could define the QS
constant into QuotingProcessor
and then statically import it in Sample
. This would be a better and more practical approach. Unfortunately, you cannot statically import things from the default package (this is by design of Java).
Conclusions
I hope this short article helped you understand the usefulness and power of the new String Templates. Feel free to “play” with this new feature like I have done in this article!
I also hope this feature will be confirmed in future Java versions. 😉