20

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.

Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
Ritusmoi Kaushik
  • 211
  • 1
  • 2
  • 6
  • what you really needed was a template processor. text block is just a text. – MNEMO Sep 01 '20 at 12:27
  • 2
    You can use String.format() to fill in variables. That's not exactly what you want, but an alternative. – Ralf Renz Sep 01 '20 at 12:27
  • @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. – Michael Sep 01 '20 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. – Brian Goetz Sep 01 '20 at 18:31
  • And for simple cases like that when you only have one variable you can also probably use `String::replace` [1] provided that no contextual escaping is needed. [1] https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/String.html#replace(java.lang.CharSequence,java.lang.CharSequence) – daniel Sep 03 '20 at 10:49
  • 1
    Does this answer your question? [How to have placeholder for variable value in java text block](https://stackoverflow.com/questions/61432347/how-to-have-placeholder-for-variable-value-in-java-text-block) – Dennis Gloss Sep 08 '20 at 15:10

4 Answers4

31

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);
Alex Shesterov
  • 26,085
  • 12
  • 82
  • 103
7

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.

Michael
  • 41,989
  • 11
  • 82
  • 128
  • 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 Sep 01 '20 at 13:11
  • @M.Prokhorov Yep, any variation on the delimiter(s) would work. – Michael Sep 01 '20 at 13:29
0

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://learn.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.

MNEMO
  • 268
  • 2
  • 11
-1

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

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72
  • "*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.). – Michael Sep 01 '20 at 12:41
  • 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 Sep 01 '20 at 12:43
  • @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 Sep 01 '20 at 13:15
  • @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 Sep 01 '20 at 13:31
  • @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. – rzwitserloot Sep 01 '20 at 13:31