string templates javastring templates java
HappyCoders Glasses

String Templates in Java

Sven Woltmann
Sven Woltmann
Last update: April 12, 2024

Breaking News: On April 5, 2024, Gavin Bierman announced that String Templates will not be released in the form described here. There is agreement that the design needs to be changed, but there is no consensus on how it should be changed. The language developers now want to take time to revise the design. Therefore, String Templates will not be included in Java 23, not even with --enable-preview.

In this article, you will find out:

  • How do string templates simplify the composition of strings from text, variables, and computed values?
  • What is a template processor?
  • Which template processors are available?

String templates were introduced as a preview feature in Java 21 as part of Project Amber. In Java 22, they were sent to a second preview round without any changes.

Status Quo of Java String Concatenation

We have several ways to compose strings at runtime using variables and calculated values. The most common ones are the following:

int a = ...;
int b = ...;

String concatenated = a + " times " + b + " = " + a * b;
String format       = String.format("%d times %d = %d", a, b, a * b);
String formatted    = "%d times %d = %d".formatted(a, b, a * b);Code language: Java (java)

Often we also use a StringBuilder, less often MessageFormat. None of the available variants is particularly good to read.

String Interpolation With String Templates

Almost every modern programming language offers the possibility of string interpolation, i.e., the possibility of evaluating placeholders in a string and replacing them with the result of this evaluation.

Precisely this (and even more, see below) is enabled by “string templates” introduced by JDK Enhancement Proposal 430.

With string templates, we can rewrite the example from above as follows:

int a = ...;
int b = ...;

String interpolated = STR."\{a} times \{b} = \{a * b}";Code language: Java (java)

The placeholders may not only contain variables and arithmetic expressions, but they may also contain any Java expression, e.g., a static method call:

String interpolated = STR."\{a} times \{b} = \{Math.multiplyExact(a, b)}";Code language: Java (java)

The placeholder may also contain quotes, and for the sake of clarity, you can split it over multiple lines and add comments (at this point, I need to turn off the WordPress syntax highlighting plugin, as the following code will overwhelm it):

String dateMessage = STR."Today's date: \{
        LocalDate.now().format(
                  // We could also use DateTimeFormatter.ISO_DATE
                  DateTimeFormatter.ofPattern("yyyy-MM-dd")
        )}";Code language: plaintext (plaintext)

We can use string templates also with multi-line strings:

int    httpStatus   = ...;
String errorMessage = ...;

String json = STR."""
    {
      "httpStatus": \{httpStatus},
      "errorMessage": "\{errorMessage}"
    }""";Code language: plaintext (plaintext)

In case you were wondering what STR. means in front of the strings, you’ll find the answer in the next section.

String Template Processor

STR is the name of a so-called template processor (more precisely: a constant of type StringTemplate.Processor automatically imported into every Java file). A template processor defines how template text and placeholders are combined. In the case of the STR template processor – as described above – the Java expressions in the placeholders are resolved, and the placeholders are replaced by the resulting values.

FMT Template Processor

Another template processor is FMT. It evaluates formatting information that precedes the placeholders – as we know it from String.format().

Here again, our multiplication example with floating point numbers rounded to two decimal places using the FMT template processor:

double a = ...;
double b = ...;

String interpolated = FMT."%.2f\{a} times %.2f\{b} = %.2f\{a * b}";Code language: Java (java)

SQL Template Processor

A template processor does not necessarily have to return a String. For example, one could implement a template processor that compiles SQL commands and returns an SQL statement – and at the same time protects against injection attacks:

String searchQuery = ...
Statement statement = SQL."""
    SELECT * FROM User u
    WHERE u.userName LIKE '%\{searchQuery}%'""";Code language: Java (java)

If you want to go deeper into the matter, I recommend reading the JDK Enhancement Proposal. It will also teach you how to write your own template processor and that a template processor does not always have to return a string.

You don’t want to miss any HappyCoders.eu article and always be informed about new Java features? Then click here to sign up for the free HappyCoders newsletter.