37

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.

6
  • what you really needed was a template processor. text block is just a text. Commented Sep 1, 2020 at 12:27
  • 2
    You can use String.format() to fill in variables. That's not exactly what you want, but an alternative. Commented Sep 1, 2020 at 12:27
  • 1
    @MNEMO Disagree. If you have used a language with template literals, like JavaScript, you will know that a feature like is extremely expressive and convenient. Commented Sep 1, 2020 at 12:36
  • 3
    There's also a new method formatted(), which is an instance version of String::format. "Hi %s".formatted(name). Works with any string expression, text blocks or not. Commented Sep 1, 2020 at 18:31
  • 1
    Does this answer your question? How to have placeholder for variable value in java text block Commented Sep 8, 2020 at 15:10

3 Answers 3

62

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);
Sign up to request clarification or add additional context in comments.

Comments

12

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.

2 Comments

That, or they could prepend """ (or " for non-blocks) with a symbol like $, at which point compiler is instructed to do its thing with contents. Prepending some symbols is a little better approach, because that would work and look the same for both flavors of String, whereas having ''' means there's no templating in "normal" string constants, or it must look different for blocks and non-blocks.
@M.Prokhorov Yep, any variation on the delimiter(s) would work.
-2

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".

5 Comments

"perhaps indicative that this feature is less useful than it sounds" I don't think so. I use it all the time in JavaScript and it's incredibly expressive. In a language like Java it has the advantage of compile-time guarantees, whereas most template libraries are destined to fail at runtime (wrong number of supplied args etc.).
I also don't think it's fair to say that its omission is evidence that they have purposely excluded it. As the JEP says, they may add it in the future. That note alone suggests that they haven't ruled it out, else they would say so. This seems more like an attempt to manage/limit the scope of the change. Even today, Java language features move very slowly compared to others out there. It seems likely to me that adding string interpolation into the mix was just too much work for the limited resources they have.
@Michael, they might add interpolation, but there's no ongoing JEP for doing so. Text blocks JEP is 4.5 years old at this point, which says to me that compiler feature is quite a way away from being shone onto us.
@M.Prokhorov I agree, and I'm also doubtful that we will ever get this feature. But I believe it's not for the reasons Reinier suggests. Of course, we can't know for sure unless a Java language designer shows up. (to be clear, I didn't disagree with this enough to downvote it, but nor do I agree with it enough to upvote it)
@Michael sure, if interpolation was initially part of the plan was excluded due to the feature having been deemed 'not suitable' for java, it would have said so. I'm just looking ahead.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.