35

How can I put a variable into Java Text Block?

Like this:

"""
{
    "someKey": "someValue",
    "date": "${LocalDate.now()}",

}
"""
informatik01
  • 16,038
  • 10
  • 74
  • 104
Dennis Gloss
  • 2,307
  • 4
  • 21
  • 27
  • 2
    Its a representation of a `String` after all. At least for now without further detail over "why not try using an existing construct like `String.format`" , the question would stand as an exact duplicate. Leaving the rest for the community to decide. – Naman Apr 26 '20 at 00:20
  • 1
    Does this answer your question [Java - Including variables within strings?](https://stackoverflow.com/questions/9643610/java-including-variables-within-strings) – Naman Apr 26 '20 at 00:24
  • I thought more about how to write java code inside the text block, `String.format` is more like a work around with which sadly I hadn't come up with... – Dennis Gloss Apr 26 '20 at 00:41
  • 1
    @DennisGlot `String::format` is not a _workaround_, it is the normal way of doing string interpolation in Java. (With text blocks, an instance version was also added, so you can say `"...".formatted(...)` if you prefer chaining.) – Brian Goetz Apr 26 '20 at 15:29

3 Answers3

40

You can use %s as a placeholder in text blocks:

String str = """
{
    "someKey": "someValue",
    "date": %s,
}
"""

and replace it using format() method.

String.format(str, LocalDate.now());

From JEP 378 docs:

A cleaner alternative is to use String::replace or String::format, as follows:

String code = """
          public void print($type o) {
              System.out.println(Objects.toString(o));
          }
          """.replace("$type", type);

String code = String.format("""
          public void print(%s o) {
              System.out.println(Objects.toString(o));
          }
          """, type);

Another alternative involves the introduction of a new instance method, String::formatted, which could be used as follows:

String source = """
            public void print(%s object) {
                System.out.println(Objects.toString(object));
            }
            """.formatted(type);

NOTE

Despite that in the Java version 13 the formatted() method was marked as deprecated, since Java version 15 formatted(Object... args) method is officially part of the Java language, same as the Text Blocks feature itself.

informatik01
  • 16,038
  • 10
  • 74
  • 104
Ryuzaki L
  • 37,302
  • 12
  • 68
  • 98
  • Could you explain, why is this not a duplicate of https://stackoverflow.com/questions/9643610/java-including-variables-within-strings? – Naman Apr 26 '20 at 00:24
  • 5
    @Naman Because that question is about conventional string syntax, while this question is specifically about text blocks. – Basil Bourque Apr 26 '20 at 00:28
  • @BasilBourque The [JEP-355](https://openjdk.java.net/jeps/355) reads - *"It is not a goal to define a new reference type, distinct from java.lang.String, for the strings expressed by any new construct."* or to read the other way round, *"A text block is a **multi-line string** literal that avoids the need for most escape sequences, automatically formats the string in a predictable way, and gives the developer control over format when desired'.* (formatted by me). Anyway, leaving further for the community to decide for the clash of thoughts added to a lack of interest in the JEP. – Naman Apr 26 '20 at 00:37
  • 6
    `String.formatted` is not "really" deprecated. In fact, it is a new method (since Java 13). It is deprecated only because it is related to text blocks, which are a preview feature. But if you use text blocks, you can as well use this method. – user140547 Apr 26 '20 at 07:08
  • 4
    https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/String.html#formatted(java.lang.Object...) it's safe to use it now – Lovro Pandžić Sep 22 '20 at 11:29
  • 1
    Regarding the deprecation: [“However, the deprecation-based approach was eventually dropped because it was confusing to see an API element introduced in the same Java SE release as it was deprecated, that is, to see @since 13 and @Deprecated(forRemoval=true, since="13") on the same API element.”](https://openjdk.org/jeps/12#:~:text=However%2C%20the%20deprecation,on%20the%20same%20API%20element.) – Holger Sep 15 '22 at 11:23
1

You can use Java's String Templates feature. It is described in JEP 430, and it appears in JDK 21 as a preview feature. Here is an example use:

String name = "Joan";
String info = STR."My name is \{name}";
assert info.equals("My name is Joan");   // true

It also supports Java's multi-line text blocks:

String title = "My Web Page";
String text  = "Hello, world";
String html = STR."""
        <html>
          <head>
            <title>\{title}</title>
          </head>
          <body>
            <p>\{text}</p>
          </body>
        </html>
        """;

Java's string templates are more versatile, and much safer, than features in other languagues such as C#'s string interpolation and Python's f-strings. For example, here is a template processor that returns not strings but, rather, instances of JSONObject:

var JSON = StringTemplate.Processor.of(
        (StringTemplate st) -> new JSONObject(st.interpolate())
    );

String name    = "Joan Smith";
String phone   = "555-123-4567";
String address = "1 Maple Drive, Anytown";
JSONObject doc = JSON."""
    {
        "name":    "\{name}",
        "phone":   "\{phone}",
        "address": "\{address}"
    };
    """;
mernst
  • 7,437
  • 30
  • 45
0

You can use Java's String Templates feature. It is described in JEP 430, and it appears in JDK 21 as a preview feature. Here is an example single-line use:

String name = "Joan";
String info = STR."My name is \{name}";
assert info.equals("My name is Joan");   // true

It also supports Java's multi-line text blocks:

String title = "My Web Page";
String text  = "Hello, world";
String html = STR."""
        <html>
          <head>
            <title>\{title}</title>
          </head>
          <body>
            <p>\{text}</p>
          </body>
        </html>
        """;

Java's string templates are more versatile, and much safer, than features in other languagues such as C#'s string interpolation and Python's f-strings. For example, string concatenation or interpolation makes SQL injection attacks possible:

String query = "SELECT * FROM Person p WHERE p.last_name = '" + name + "'";
ResultSet rs = conn.createStatement().executeQuery(query);

but this variant (from JEP 430) prevents SQL injection:

PreparedStatement ps = DB."SELECT * FROM Person p WHERE p.last_name = \{name}";
ResultSet rs = ps.executeQuery();

and you could do something similar to create an HTML data structure, via a string template that quotes HTML entities.

mernst
  • 7,437
  • 30
  • 45