Core Java

Guide to String Templates in Java 21

Java 21 introduced a powerful new feature called String Templates, offering a more versatile and secure way to construct strings compared to traditional methods. This article delves into String Templates, exploring their syntax, capabilities, and usage with detailed code examples.

1. Strings in Java

Conceptually, Java Strings are sequences of Unicode characters. For example, the string "JavaCode\u2122" consists of the nine (9) Unicode characters J,a,v,a,C,o,d,e, and TM.

Java offers several ways to compose strings. Let’s explore some of the most commonly used methods:

1.1 Concatenation Operator (+)

Java allows us to use the plus sign (+) to concatenate (join) two strings:

String firstName = "John";
String lastName = "Thomas";
String fullName = firstName + " " + lastName;
System.out.println(fullName); // Output: John Thomas

1.2 StringBuilder and StringBuffer

Java provides two specialized classes, namely java.lang.StringBuffer and java.lang.StringBuilder, tailored for string manipulation tasks such as concatenation, along with supplementary functionalities like insertion, replacement, and string searching. While StringBuffer, introduced with Java’s inception, ensures thread safety, StringBuilder, introduced in Java 5, serves as an API-compatible, more efficient alternative, but lacking thread safety.

When dealing with a large number of string manipulations or iterations, using StringBuilder is more efficient than concatenation:

StringBuilder builder = new StringBuilder();
builder.append("Hello");
builder.append(" ");
builder.append("World");
String result = builder.toString();
System.out.println(result); // Output: Hello World

1.3 String.format() and String.formatted()

The String.format() method is a tool for string formatting. It takes two arguments – Format String (A string containing placeholders ({}) to be replaced with the provided arguments) and Arguments (The values to be inserted into the placeholders). The method supports various format specifiers like %s(string), %d(integer), %f(float), etc., to control the formatting of arguments. An example is:

String name = "Alice";
int age = 30;

String formattedString = String.format("Hello, my name is %s and I am %d years old.", name, age);
System.out.println(formattedString);

The above code outputs:

Hello, my name is Alice and I am 30 years old.

String.formatted() on the other hand was introduced in Java 15+, provides a more concise and readable way to format strings. Here’s the equivalent code using String.formatted():

String name = "Alice";
int age = 30;

String formattedString = "Hello, my name is %s and I am %d years old.".formatted(name, age);
System.out.println(formattedString);

This code also outputs:

Hello, my name is Alice and I am 30 years old.

1.4 MessageFormat Class

MessageFormat is a class specifically designed for internationalization and localization, allowing us to format messages with placeholders. Similar to String.format(), it uses curly braces {} to indicate placeholders. Here’s an example demonstrating its usage:

        // Define the message pattern with placeholders
        String messagePattern = "Welcome, {0}! Today is {1, date, full}.";

        // Create a MessageFormat object
        MessageFormat messageFormat = new MessageFormat(messagePattern);

        // Provide arguments for the placeholders
        Object[] arguments = {"Alice", new Date()};

        // Format the message with arguments
        String formattedMessage = messageFormat.format(arguments);
        System.out.println(formattedMessage);

This code outputs:

Welcome, Alice! Today is Tuesday, March 5, 2024.

Each of the methods mentioned has its effectiveness, yet they come with limitations. Either they make the code hard to understand or make it too long for simple tasks. Java 21 introduced a preview feature called string templates, bringing a much-anticipated addition to the string formatting landscape.

2. Motivations for String Templates

The introduction of string templates aims to address several shortcomings of the existing methods:

  • Readability: String templates strive to enhance code readability by enabling a more natural way to embed expressions within strings. This simplifies the process of constructing complex strings, making the code easier to understand and maintain.
  • Type Safety: String templates offer the potential for improved type safety. By embedding expressions directly within the string, the compiler can perform type checks, potentially reducing runtime errors related to incompatible argument types.
  • Flexibility: String templates provide a foundation for future enhancements. Libraries and frameworks can leverage this feature to define custom formatting syntax, extending its capabilities and catering to specific needs.

2.1 Benefits of String Templates

While still under preview in Java 21, string templates present several potential benefits:

  • Cleaner and more concise syntax: Embedding expressions directly within strings leads to less verbose and more readable code.
  • Reduced boilerplate code: Simplifies string construction by eliminating the need for explicit concatenation or format specifiers.
  • Improved maintainability: Easier to understand and modify strings due to the clear and intuitive syntax.

3. Key Concepts of String Templates

  • Template Expressions: These expressions are embedded within string literals, enclosed in curly braces {}. They can hold variables, expressions, or even method calls.
  • Template Processors: These classes are responsible for evaluating the expressions and assembling the final string. Java provides built-in processors like STR, FMT and RAW.
  • Template: This is the string literal containing the static text and embedded expressions separated by a dot (.).

3.1 Basic Usage

Here’s a simple example illustrating basic String Template usage:

import static java.lang.StringTemplate.STR;

public class StringTemplatesExamples {

    public static void main(String[] args) {

        String name = "Alice";
        String greeting = STR. "Hello, \{name}!";
        System.out.println(greeting); // Output: Hello, Alice! 
       
    }
}

3.2 Template Expressions

Template expressions are the heart of String Templates in Java 21. They allow us to embed dynamic content within string literals, making our code more readable and maintainable.

3.2.1 Anatomy of a Template Expression

A template expression is enclosed in curly braces {} and can contain various elements:

Variables: We can directly reference variables declared within the current scope.

String name = "Bob";
String message = STR. "Hello, \{name}!"; // Uses the variable 'name'

Expressions: Any valid Java expression can be used within the curly braces. This allows for calculations and manipulations.

int age = 25;
String info = STR. "You are \{age * 365} days old."; // Performs calculation
System.out.println("" + info);

Method Calls: We can call methods on objects directly within the template expression.

LocalDate today = LocalDate.now();
String formattedDate = STR. "Today's date is \{today.format(DateTimeFormatter.ISO_DATE)}";//Calls a method
System.out.println("" + formattedDate);

Nested Expressions: Template expressions can be nested within each other, allowing for complex logic within our strings.

        String product = "T-Shirt";
        double price = 19.99;
        String discount = STR. "The \{product.toUpperCase()} is on sale for \{price * 0.9}"; // Nested expressions
        System.out.println("" + discount);

3.3 Template Processors

Java provides three built-in template processors:

  • STR: The default processor, evaluates expressions and directly interpolates them into the string.
  • FMT: Similar to STR, but allows using format specifiers like printf and handles locale information.
  • RAW: Doesn’t automatically process the template. We can use it to access individual components like string literals and expression results separately.

Let’s explore some examples using each built-in processor:

3.3.1 Example using STR Template Processor

The STR Template processor performs basic interpolation without any formatting options.

        String name = "John";
        String age = "30";

        // Greeting with variable interpolation
        String greeting = STR. "Hello, \{name}! You are \{age} years old.";
        System.out.println(greeting); 

Multi-Line Expressions

We can use triple quotes (""") for multi-line string literals:

public class StringTemplatesExamples {

    public static void main(String[] args) {

        String name = "John";
        String age = "30";

        // Greeting with variable interpolation
        String greeting = STR. "Hello, \{name}! You are \{age} years old.";
        System.out.println(greeting); // Output: Hello, John! You are 30 years old.

        // Multi-line greeting
        String message = STR. """
        Welcome, \{name}!

        This is a multi-line message
        using the STR processor.
        """;
        System.out.println(message);

  }
}

The above code snippet produces the following output:

Fig 1.0 Output of using STR Template processor with multiline expressions - java 21 string templates
Fig 1.0 Output of using STR Template processor with multiline expressions – java 21 string templates

3.3.2 Example using FMT Template Processor

FMT Template processor is similar to STR, but allows using format specifiers like printf for finer control over formatting.

        double pi = 3.14159;

        // Formatted value of pi
        String piString = FMT. "The value of PI is: %.2f, \{pi}";

        System.out.println(piString); // Output: The value of PI is: 3.14

Please be aware that as of today, the FMT Template Processor appears to be non-functional in the latest JDK version.

3.3.3 Example using RAW Template Processor

Doesn’t automatically process the template. Useful for accessing individual components like string literals and expressions separately.

        String name = "Alice";	
        
        StringTemplate st = RAW."Greetings \{name}.";
        String message = STR.process(st);
        System.out.println("" + message);

Important Note: Remember that String Templates are currently a preview feature in Java 21. We have to use the --enable-preview command for running the code.

4. Conclusion

String templates mark a significant step forward for string formatting in Java. Their introduction addresses limitations of existing methods while offering potential for improved readability, type safety, and security. As the feature evolves, it holds the promise of further enhancing the developer experience and making string manipulation in Java more efficient.

5. Download the Source Code

This is an article on Java 21 string templates.

Download
You can download the full source code of this example here: Guide to String Templates in Java 21

Omozegie Aziegbe

Omos holds a Master degree in Information Engineering with Network Management from the Robert Gordon University, Aberdeen. Omos is currently a freelance web/application developer who is currently focused on developing Java enterprise applications with the Jakarta EE framework.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button