How can i add variables inside Java 15 text block feature?

Viewed 4992

Just came across a new feature in Java 15 i.e. "TEXT BLOCKS". I can assume that a variable can be added inside a text block by concatenating with a "+" operator as below:

String html = """
          <html>
              <body>
                  <p>Hello, """+strA+"""</p>
              </body>
          </html>
          """;

But are they providing any way so that we can add variables the way which is becoming popular among many other languages as below:

String html = """
          <html>
              <body>
                  <p>Hello, ${strA}</p>
              </body>
          </html>
          """;

This question might sound silly but it may be useful in certain scenario.

4 Answers

Java 15 does not support interpolation directly within text blocks nor plain string literals.

The solution in Java 15 is to use String.formatted() method:

String html = """
      <html>
          <body>
              <p>Hello, %s</p>
          </body>
      </html>
      """.formatted(strA);

From the spec for text blocks:

Text blocks do not directly support string interpolation. Interpolation may be considered in a future JEP.

"String interpolation" meaning

evaluating a string literal containing one or more placeholders, yielding a result in which the placeholders are replaced with their corresponding values

from Wikipedia


As stated above, maybe we'll get it in the future. Though it is difficult to say how they could possibly implement that without breaking backwards compatibility -- what happens if my string contains ${}, for example? The Java language designers rarely add anything that is likely to break backwards compatibility.

It seems to me that they would be better off either supporting it immediately, or never.

Maybe it would be possible with a new kind of text block. Rather than the delimiter being """, they could use ''' to denote a parameterized text block, for example.

As already discussed, this is not possible in JDK15 and you cannot change that fact.

But, I suppose you are trying to suggest a thing like this in C# language.

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated

Although this is just a syntax sugar thing over string.Format() method in C# (which is a counterpart of String.format() in Java), apparently it is nice if we can have this in Java. This is an extension to the existing way of describing string literal in the language syntax, but of course this can be easily adapted onto text block specification as well.

If this is what you have in your mind, you can make a proposal to Java Community Process to expand Java Language Specification. This is very much lighter syntax/semantics enhancement than adding full-featured template engine in Java Compiler/Runtime specification, and it is possible that they would agree with you.

As user @Michael mentioned: No. 'they' (team Project Amber, who are implementing JEP 368) are not providing any way to interpolate the string in the text block.

Note that I somewhat doubt it'll ever happen. For starters, there is the backwards compatibility issue; any such attempt to introduce interpolation requires some marker so that any existing text blocks aren't all of a sudden going to change in what it means depending on which version of javac to invoke.

But more to the point, you yourself, asking the question, can't even come up with a valid example, which is perhaps indicative that this feature is less useful than it sounds. It looks like you came up with a valid use case, but that's not actually true: If what you wrote would compile and work, then you just wrote a webapp with a rather serious XSS security leak in it!

The point is, what you really want is 'templating', and whilst templating sounds real simple (just evaluate this expression then shove the result into the string right where I typed the expression, please!) - it just isn't. Escaping is a large reason for that. But you can't blanket-apply the rule that ${strA} in a text block means: Evaluate expression strA, then HTML escape that, then put it in, for two reasons: Who says that the string you're interpolating things into is HTML and not, say, JSON or TOML or CSV or whatnot, and who says that the interpolation I desire requires escaping in the first place? What if I want to dynamically inject <em> or not, and I don't want this to turn into &lt;em&gt;?

Either we update the langspec to cater to all these cases and now we're inventing an entire templating system and shoving that into a lang spec which seems like a job far better suited to a dedicated library, or we don't, and the feature seems quite useful but is in fact niche: Either you rarely use it, or you have security and other bugs all over your code base - any lang feature that invites abuse is, and I'd hope one would agree with me on this - not a great feature.

Yes, many languages have this, but the current folks who get to decide what java language features make it into future versions of the language seem to be in the phase that they acknowledge such features exist and will learn lessons from it, but won't add features to java 'just because all these other languages all have it' - some thought and use cases are always considered first, and any such analysis of interpolation on string literals probably leads to: "Eh, probably not a worthwhile addition to the language".

Related