JEP draft: String Templates (Final)
openjdk.org
openjdk.org
f"" vs STR."" is really a quite minimal difference, and I think worth it. Having the "." operator here mean "interpolate RHS using LHS" seems a nice balance between terseness and explicitness.
As for "\{" being a divergent choice, frankly who cares.
var $ = STR;
var $h = new HtmlTemplateThing();
var $j = new JSONTemplateThing();
var name = "John";
var s = $."Hello \{name}";
// HTML escaped
var h = $h."<b>\{name}</b>";
// JSON escaped
var j = $j."""
{ "name" : "\{name}" }
"""; // JSON escaped
I love this one: var $db = new DBConnectionTemplateThing();
// SQL Escaped and processed
PreparedStatement st = $db."select * from table where name = '\{name}'";
Or: var $x = new XMLTemplateThing();
// XML escaped and parsed
Document d = $x."<xml>\{name}</xml>";
This is pretty powerful. They selected \{ for the start of expressions because of the legacy of Java Expression Language (EL) which came from JSP and JSF.Doesn't look that terrible to me.
https://developer.apple.com/documentation/swift/stringinterp...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...
I used it to support a LiveView implementation for Java: https://github.com/floodfx/undead
Sure the syntax isn't "pretty" but understandable and you get used to it like anything else.
The JEP explains why Java is getting string templates and is not getting string interpolation (as a language feature).
String name = "Joan";
String info = "My name is \{name}";
| error: processor missing from template expression
Were literals like "\{" always causing an error?It's the reason they didn't chose "${" like many other languages. Because that's a valid sequence in a string literal.
`\{` as an interpolation leader would make sense if untagged string literals became implicit STR templates, but that's not the case.
In which case using `\{}` as the interpolation signal is completely unnecessary, because the new syntax already solves the backward compatibility concerns.
Using just `{x}` like C# and Python, or `$x`/`${x}` like Kotlin, would have sufficed and made the syntax a lot more palatable.
So would using postfix format specifiers, because that printf-style prefix garbage is just gnarly.
Too often I see experienced developers using string interpolation for SQL and not realising it's open to injection. I feel the document's intentions are good but because the implementation looks so verbose they should make it as frictionless as possible to gain wider adoption. Else all that's going to happen is people will only ever use STR.
var q = DB."SELECT foo FROM bar WHERE a = \{b}"; // PreparedStatement?
var results = conn.execute(q); // ResultSet
is shorter and easier to write than the non-safe alternative.That said, I wonder how often people are writing queries out by hand like that these days vs using ORMs or jOOQ.
Yes, we already have that problem solved with JPQL or even just plain prepared statement but that’s never stopped anyone…
And yes, you could also write a message formatter the current Java that does that…
"..." + foo + "..." + bar + "..."
and STR."...\{foo}...\{bar}..."
is negligible. And then the syntax FOO."..."
would at least imply that some special processing is going on. C# $"{x} plus {y} equals {x + y}"
Visual Basic $"{x} plus {y} equals {x + y}"
Python f"{x} plus {y} equals {x + y}"
Scala s"$x plus $y equals ${x + y}"
Groovy "$x plus $y equals ${x + y}"
Kotlin "$x plus $y equals ${x + y}"
JavaScript `${x} plus ${y} equals ${x + y}`
Ruby "#{x} plus #{y} equals #{x + y}"
Swift "\(x) plus \(y) equals \(x + y)"
Java STR."\{x} plus \{y} equals \{x + y}"> String interpolation is dangerous > Can we do better?
For the 'injection' case, they could define an annotation which stops interpolation on a provided parameter, and provide a more verbose method to handle templated interpolation correctly.
A sample syntax by JetBrains is below. [0] In future, this could be leveraged to block/warn against dangerous interpolations
@Language("SQL") // This adds SQL highlighting, encouraging developers to use it
String query = "SELECT * FROM Person p WHERE p.last_name = '${name}'" // future warning/error
[0] https://www.jetbrains.com/help/idea/using-language-injection...1. Introducing syntax for new kind of string literals (like JS did)
2. Make some kind of explicit function/constructor call (like they ended up doing).
Advantage of 2 is that it doesn't require any new support from IDEs/parsers/code quality tools/etc. It is slightly more verbose, but not as verbose as some other Java syntax. IMO they've made the right decision.
Furthermore, they went on to use a printf-style formatting spec prefixing the template leader.
> Advantage of 2 is that it doesn't require any new support from IDEs/parsers/code quality tools/etc.
Of course it does, the sequence "IDENTIFIER, PERIOD, STRING LITERAL" is currently invalid, anything beyond a tokeniser should choke on it.
- no strange leading character(s) (per C#, VB, Python, Scala, and now Java)
- templated strings are actually distinguished, so don't have to worry about accidentally running into template literals in normal strings (unlike Groovy, Kotlin, Ruby)
- the distinguishing mark appears at the end as well as the beginning, for slightly better legibility.
- Swift is quite nice in that the backslash is already an escape character for normal strings, so no issue with accidental use, but {} would have been a better choice than () as the former are rarer in normal strings.
There are no strange leading characters in Java, either. A template expression is a special case of an instance method call (it's a call to the `process` method on the template processor), and the "leading characters" are the same ones Java already requires for all instance calls. There's nothing strange about them; what is new (and therefore possibly strange) is the use of `"` for the method call instead of a method name followed by `(`. In other words, the new syntax Java added is what follows the dot in the method call to `process`; everything up to and including the dot is normal Java syntax. This is important to emphasise that a template string expression is an a method call that may (although normally shouldn't) even have a side effect.
> templated strings are actually distinguished, so don't have to worry about accidentally running into template literals in normal strings
Same here. `\{` inside a string remains a syntax error, as it always has been. Also, Java is typed (and the template expression requires a receiver of type StringTemplate.Processor) and there cannot be any ambiguity, and so it's unnecessary to introduce yet another punctuation mark. JS needed further distinguishing syntax because it is untyped.
"my normal string"
`my templated string`
vs
"my normal string"
STR."my templated string"
probably we can agree which looks cleaner (though I grant, maybe not as 'pluggable')
So the question that's relevant to the core of this feature is, which looks cleaner:
SQL."..."
or SQL`...`
Because this is an actual method call, because Java's type safety and the fact that `\{` is a syntax error in a string means that string and template literals cannot possibly be confused, I think that the former is nicer and clearer for Java programmers and it's only longer by a single character; in fact, I would say that the latter would look very foreign (you could ask whether SQL"..." would be better, but this is an instance method call, and dropping the standard dot, I would argue, would not make things better).You can see it better if you look at the JS examples here (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...), such as:
console.log.bind(1, 2)`Hello`;
Which, in Java syntax, would be written as: console.log.bind(1, 2)."Hello";
I think it's much less weird for a Java programmer.Also, it's not about "plugging in" other processors. The processor is chosen by the library. If a library offers an HTML processor as part of its API but not a method that takes a string, you simply cannot use STR even if you wanted to. The processor is more a constraint imposed by the API than a plugin you choose to use or not (as the type of the template expression is determined by the processor, and for the interesting processors it is not a string at all but rather a PreparedStatement or some JSON class or HTMLNode).
JS offers string interpolation in addition to string templates (or "tagged template strings", as they're called in JS), but we don't offer string interpolation as a Java language feature at all, because it's really dangerous and should be discouraged (certainly not made easier to use than safer templates). But supposed we did want to offer string interpolation in Java, then its syntax would simply be "...". There would be no confusion between a string and a string template even then.
You can agree or disagree with the JEP's goal, but pointing out that the JEP manages to discourage the very thing that it sets out to discourage merely acknowledges that the goal is met.
That idea is evidently idiotic as demonstrated by javascript which has this exact feature, in a better form (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...): the most common template literals by far are untagged.
Using '\' instead of '$' does not allow $variable as a shortcut to ${variable} making the syntax objectively harder to read.
Using '\' cleverly helps to detect when the processor is missing at compile time but it does not matter because the syntax mandates a big STR in front.
True, but so was the argument I responded to (JS did it differently) and this is, after all, the internet. But there was also another point I was trying to make, which is that some people seem to have it as their null hypothesis that Java's designers get things wrong or don't do what the people want even though they are not only among the most experienced language designers around but also among the most consistently successful, and usually by a pretty wide margin. I think that means that at the very least they deserve the benefit of the doubt and perhaps another moment of contemplation.
> Better listening to the foot soldiers than staying in your high tower.
Which is why the designers didn't just trust their guts and experience, but designed the feature in an iterative process with actual "foot soldiers" trying it out (as most new Java features are designed, and as the Preview process was created to support). The criticism, on the other hand, seems to mostly come from people who have not actually tried it out, and it is they who are staying in their high tower.
When designing new Java features and asking for feedback we always emphasise that speculating is something anyone can do, and what we need is people trying out the prototype or preview and reporting on their actual experience. Such feedback is always valuable and taken seriously. On the other hand, speculation offered by people who have both given the matter less thought and who have had less experience with the feature than its designers is usually not very useful.
It is really very easy for a Java programmer to have an actual impact on the design of new features: Step 1 — try the feature for a while in EA or in Preview; step 2 — report on your experiences to the mailing list. If someone can't even spend the time to do that, how can we know that they've spent more than 30 minutes thinking about the problem before sharing their speculation that we must have done something wrong?
Now, it is true that while we know that string interpolation is problematic, we can only speculate that offering it only as a special case of string templates would improve matters. But we figured that if, despite our analysis, we end up being proved wrong, it would be an easy matter to also offer string interpolation as a language feature (e.g. by making it the default processor).
> Using '\' instead of '$' does not allow $variable as a shortcut to ${variable} making the syntax objectively harder to read.
Python (f-strings), JS, C#, and Ruby -- the most popular language that have had either string interpolation and/or string templates before Java -- also don't allow for such a shortcut (I believe the only top language that does support this shortcut is PHP), and if quite a few language designers didn't think that the shortcut was a significant advantage I don't know how "objective" you can claim it to be.
$ also creates some other difficulties, as it is quite common in Java templating libraries (even in JS, the syntax used by templating libraries differs from that used by the language, otherwise it causes bigger annoyances). It would mean that $ would need to be escaped in some contexts and not in others, making adoption of the feature less smooth than we'd want (see https://mail.openjdk.org/pipermail/amber-spec-experts/2023-A...).
> Using '\' cleverly helps to detect when the processor is missing at compile time but it does not matter because the syntax mandates a big STR in front.
Like all instance calls in Java, this instance call also mandates a receiver; it's not some special prefix. If you don't like the "big" STR you can assign that particular template processor object a different name, including one named `$` if you like, because that's a valid Java identifier. I.e. you can do:
var $ = STR;
$."Hello \{x}!"> Iterative process
please send a link to a video of a designer from Oracle presenting the string templates at a conference. This is not Loom, there is no iterative process.
> Python, JS, and C# also don't allow for such a shortcut
The syntax of C# or Python is also lightweight, fine by me.
> it's not some special prefix
I get that, but not using a constant like STR is an anti-pattern, as you said it's a virtual method call.
> The criticism, on the other hand, seems to mostly come from people who have not actually tried it out
Ask designers to go to conferences and you will get real feedback.
Sorry to disappoint (or not) but much of the technical leadership are the same people...
> please send a link to a video of a designer from Oracle presenting the string templates at a conference.
How about not one video but two, not of any designer but of the chief language designer talking about the feature not at any conference but at what is probably the biggest Java conference?
https://youtu.be/TIHx6MNt79Y?si=Qwj0ER-yxlS-Flxq&t=1972
https://youtu.be/DlTUMjg7DD0?si=6urFyuyF_jCtZ0H-&t=1099
> This is not Loom, there is no iterative process
a. you're wrong — the discussion and iteration have taken place on the amber-dev and the amber-spec-experts mailing lists — and b. I've received my share of accusations of "not listening" (and sometimes even worse) on Loom. It may not have been from you, though. :)
As always, feedback that follows actual usage is taken very seriously and has a significant impact.
You're right, however, that it's a much smaller feature than virtual threads, and so the public part of the design process didn't last for over four years but only for a little over two years (https://mail.openjdk.org/pipermail/amber-dev/2021-September/..., https://github.com/openjdk/amber-docs/blob/master/site/desig...).
> The syntax of C# or Python is also lightweight, fine by me.
Python has string interpolation but doesn't have string templates; Java has string templates but doesn't have string interpolation as a language feature. You're comparing syntax for two different features. As for C#, Java-like string templates can be mimicked [1], but the syntax isn't really lighter-weight. Instead of `SQL."SELECT * FROM SomeTable WHERE Age = \{age} AND Name = \{name}"` you'd write `SQL($"SELECT * FROM SomeTable WHERE Age = {age} AND Name = {name}")`; note that the method call to SQL is necessary to get a similar feature to Java's.
> I get that, but not using a constant like STR is an anti-pattern, as you said it's a virtual method call.
It's just a final field. You can do `final StringTemplate.Processor<String, RuntimeException> $ = STR;` and it's just as much of a "constant" as STR is. Of course, whether or not you should make string interpolation easier is up to you; after all, the reason we didn't add string interpolation to the language is because we think that making it easier is a bad idea given the vulnerabilities it has caused.
> Ask designers to go to conferences and you will get real feedback.
But they do. But just to clarify, feedback about a feature is from people who've actually used it; otherwise it's just a speculative opinion.
[1]: https://bengribaudo.com/blog/2021/04/13/5596/intercepting-st...
Processor should not require to allocate a list of objects do to string templating. Only STR and FMT get good perf because they are specialized by the compiler.
Sort of. The specialisation happens for any user of MethodHandle.invokeExact, which is what those processors use (i.e. the compiler doesn't specifically know about STR and FMT), it's just that the MethodHandle API for template processors is not yet public. I expect it will be made public later on.
This seems just like another feature of the JVM mother language that diverges from the implementation of other often-used JVM languages like Kotlin (thinking of nullability, type reification and structured concurrency and record types). It will be interesting to see what happens when Kotlin is continued to be pushed as the language for Android etc. while Java is being used by the majority of JVM devs.
The existing ${it} syntax is tied to string on the output, so it can't be repurposed. The java approach on the other hand keeps the output generic, so that it would also keep the door open for similar not-string compatibilities in off-JVM kotlin implementations. Whereas the ${it} the syntax kotlin already has couldn't do that. An approach like changing its semantics to define something that isn't a string when it exists at a StringTemplate.Processor call site would be terrible I think, php-grade terrible. At least as long as they don't also introduce that formatter-dot-template syntax which I'd consider a pointless redundancy with what kotlin already has: formatter{template} is already possible, expect for a way to write a template literal that resolves to something other than string.
What I certainly wouldn't expect is anything reminiscent of "automatically imported into every Java source file".
It's certainly a very visible language and one often talked about, but if you look at Google trends for Java versus kotlin you're looking at about 10% of the adoption that Java has or less.
In 1996, I thought java would be the new COBOL, and could endure for 20 years - now almost 30. This prioritization of "whole product" concerns, like security (bobby tables) and error-proneness, ensures longevity.
Also capture developers and codebases with its intricate magical features.
I mean, "${x}" could already be a literal in strings before, but they have the <processor>. prefix to the string, which no old code would have. One needs to actively use it, and so that someone can also actively check not to write an unescaped ${x} when they don't want interpolation (like in other languages that use it).
Also the whole processor for escaping is imho ill-conceived. Escaping for a specific language like SQL should happen on the formatter instructions level, e.g.
"SELECT airport_code FROM airports WHERE name != '%sql.string\{surname}'"
->
SELECT name FROM table_foo WHERE surname != 'O''Hare'
or something to that effect (and similar for sql.identifier etc).This way you could easily write classes with collections of methods to format a specific kind of language's values - and not have write a full formatter that parses and understands the whole string in context (as I assume is the case now, if you don't just use the naive STR/FMT one, as 99% will do).
Especially since you might need to handle multiple languages escaping rules in the same template, if you include strings for multiple languges/contexts in your template. What you do for that? Write the cartesian combo of template processors and make each understand and parse multi-language string tokens?
There are multiple reasons to prefer \:
1. In Java, \ is already the character that signifies that what follows has a special meaning, while the use of $ is foreign (to the language).
2. `\{` is a syntax error inside string literals, which means it appears nowhere inside string literals, while $ is fairly common; it would also mean that $ will need to be written differently inside string and string template literals.
3. The use of $ for interpolation is common in Java templating libraries, and it's preferable for the language to use something different (in JS, where $ is used by the language, templating libraries also use something else, like `{{`). See https://mail.openjdk.org/pipermail/amber-spec-experts/2023-A...
> or something to that effect (and similar for sql.identifier etc).
You can already do that if you want:
X."blah \{sqlString(x)} blah";
But this feature is being added to Java to solve the pretty serious problem of code injection, and so the more important thing is the selection of the processor, which ensures safety, i.e. an HTML API will offer an HTML processor and will not accept strings. Remember, string templates are most useful when what they produce is not a string, but rather construct a specific API entity.My take is that it will do little for code injection. Most programmers will use STR/FMT, and unless they offer an HTML or an SQL processor in the stdlib, they wont be used.
>Remember, string templates are most useful when what they produce is not a string, but rather construct a specific API entity
Sure, but the processor can do little short of implementing full parsing to understand the context of say HTML or SQL, right?
New processors obviously can't be used unless they're offered by a library, but when they are, they must be used. The libraries simply won't offer an API based on strings (and, therefore, interpolated strings), or if they already do, they will be able to deprecate them. If an HTML library has no API that takes strings, then STR/FMT simply can't be used. The library can enforce the safety of its API.
> Sure, but the processor can do little short of implementing full parsing to understand the context of say HTML or SQL, right?
Yes, that's the point. An HTML library will offer an HTML processor, and similarly for a JSON or SQL library. I'm not apprised of the exact status, but I believe that the team specifying JDBC is looking into offering a SQL processor as part of JDBC.
This is covered in the article under "Alternatives", in the section beginning with:
> For embedded expressions in string templates, we considered adopting the ${...} syntax from the Java EE Expression Language (EL) rather than \{...}. However, this would force developers to escape every $ sign in the literal text of a string template while continuing to write $ without escapes in string literals and text blocks. This inconsistency could all too easily lead to errors.
...
> With the syntax we have chosen, frameworks can ease migration by providing a template processor that understands EL syntax. Developers can continue using ${...} while also having access to the Java environment via \{...}:
The other side is that now they'll make them think they can also write \{foo} in string literals and text blocks, and they'll find out it doesn't work.
It also seems to be a very "think of the morons" point to raise.
String name = "Joan";
String info = "My name is \{name}";
| error: processor missing from template expressionJust different, and using dollar sign adds another shift press.
Much more older and common use and association (even their own "Java EE Expression Language" uses it), and not confused with escaping a character (like \n, \t) etc.
Pricinple of least surprise, avoiding NIH, and stuff.
That was one of the main reasons not to use it; even in JS templating libraries use different syntax from that of the language's $ (see my other comment).
> and not confused with escaping a character (like \n, \t) etc
That would not be a confusion at all but the very point: \{ is just like \n or \t, i.e. gets a special interpretation rather than a literal one.
> Pricinple of least surprise
\ in Java is standard for that purpose (special interpretation in a literal); it is $ that is foreign.
> avoiding NIH
That is not so much of a principle, although it could be if the language was rejecting some otherwise universal choice, only that's not the case here at all. Of the other popular language with either a similar feature to Java's string templates or with string interpolation -- JS, Python, PHP, C#, and Ruby -- only JS and PHP use $ (and only PHP uses $ with the "shell" shortcut of $x). Or, if you only want to look at the "big three" -- JS, Python, and Java -- each has a different syntax from the other two, and only one uses $. Even if you look at all programming languages in the world, only a minority of programmers using a language with string templates and/or string interpolation use one where $ is used for the value syntax. Not only is it not a near universal choice, it's a minority choice.
Java could do the same to change the behaviour of `$` inside a string (along with a project-level config to make this the default).
Let developers opt-in to better syntax, rather than using significantly worse syntax to support legacy code
https://learn.microsoft.com/en-us/dotnet/csharp/nullable-mig...
STR."\{STR."""
\{hey}
"""}"Every other language is susceptible to SQL injection style attacks. Not Java specific.
Elixir has string interpolation and custom "templates" or whatever they are called without the ugly syntax:
~h"custom one"
~s"custom two"
etc.If the string template is prefixed by a processor STR."foo" instead of "foo" then you do not need \{variable} instead of $variable.
Much easier to accidentally write something that boils down to
"\{bobby}"
where it should have been SQL."\{bobby}"
than STR."\{bobby}"
instead of SQL."\{bobby}"
(i admit that this argument would work better if STR was typographically more different from the name you'd inevitably use for an SQL statement processor)And editors will use different colors.
Using \ or $ is not about backward compatibility but about ergonomics.
Classic Java though. Take a well established pattern, implement it 10 years late, and somehow make it worse.
If the argument is along the lines of "the market is stupid," then surely that's something that can be exploited. In fact, that was Paul Graham’s point over 20 years ago in Beating the Averages: if a language is superior then it should confer a market advantage. And yet, that's not happening to Java.
If the argument is about momentum, then after 20 years of "surely this is the last nail in the coffin," clearly there is some misestimate of the importance of various factors.
So to me it looks like either the purported mistakes aren't really mistakes at all, or they are but clearly don't matter much. Is there another possibility?
Why the heck did they make it so verbose, though, in terms of number of required characters?
We must viscerally react and show our disdain for this thing in order to be approved of by the group.
I don't think this is where I'm coming from, at all, yet the snark in your response seems like the very thing you're railing against.
AFAIK C++ requires explicit formatting (even if it's compile-time verified), and Rust only has extremely restricted interpolation (you can only interpolate variables, it does not support expressions, and you still have to use formatting macros for interpolation to trigger).
On the other hand, the idea of having to know the details of a half-assed, janky, mini-DSL built in a panic by a dev who left six months ago fills me with dread.
This is mostly useful to library authors, the textbook example being a safe SQL interpolator mentioned in the JEP.
Javascript has had this feature ever since ES6 template strings were introduced and I've yet to see it abused (although I'm sure some folks have). I regularly wish Python's f-strings had custom processors, as it allows creating more convenient safe APIs, instead of having to hunt down idiots who build queries with f-strings because that's more convenient than using the safe-SQL-composition (to say nothing of query builders) they're provided with.
I don’t see why this is better than messageformat in any case? I think you might save typing like 6 whole characters? I don’t understand the value at all, perhaps I’m missing something? Just please no ‘it’s prettier’ nonsense.
I'm happy Java enhancements don't settle for half-baked features, and carefully avoid backwards compatibility issues. Yes the syntax is verbose like that of many recent features (like sealed classes) but honestly given modern tooling, who cares?
I can't get over the ugly `\{someVar}`. It will be easily confused as the `{` character is being escaped, rather than a template. `${someVar}` was a much better option.
It looks like the prefix is pluggable so you can use different template processors, STR is just the default:
> STR is a template processor defined in the Java Platform. It performs string interpolation by replacing each embedded expression in the template with the (stringified) value of that expression.
> FMT is another template processor defined in the Java Platform. FMT is like STR in that it performs interpolation, but it also interprets format specifiers which appear to the left of embedded expressions.
> Developers can easily create template processors for use in template expressions.
This is similar to Javascript's `tagged templates`: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe.... Python's f-strings are very much lacking that.
Although I do agree that the syntax, both of the prefix and the interpolation symbol, is awful.
STR is not a prefix but simply the name of the variable referencing the receiver (template processor) of the call, i.e. you can do:
var x = STR;
x."....";
In Java, making instance method calls requires a receiver to the left of a `.`. Even though template processing has special syntax, it is still a call to an instance method defined by a normal Java interface, and so, as always, requires a receiver. The new syntax here is what's to the right of the `.`; what's to the left is old syntax.> It will be easily confused as the `{` character is being escaped
It is being escaped, and so reading it as being escaped is the correct and intended understanding. Just like `\n` or `\t`, `\{` means that the next character has a special meaning, as it always does in Java. There was no need to introduce yet another escape sequence; the old one works just fine.
That is THE problem. You can use StringBuilder more easily than this ugly thing. When you write code in IDE (I hope so), writing `.append()` is actually easier than this `\{}` dreadful thing.
> It is being escaped, and so reading it as being escaped is the correct and intended understanding. Just like `\n` or `\t`, `\{` means that the next character has a special meaning, as it always does in Java. There was no need to introduce yet another escape sequence; the old one works just fine.
But what about the `}` after the expression? Who/what is escaping that? It should make it clear that this is a special syntax that does some special things. `\` is sort of universal escape character. Putting it in here feels wrong. Again, that's me (along with some other), and you definitely can disagree.
How long have you been using string templates? If you've had a bad experience, please report it to the amber-dev list. If it's speculation, I suggest you actually try the feature for a while.
Also, I think you may have misunderstood what this feature actually does (please read the JEP). StringBuilder produces strings, but string templates are most powerful when you're not producing strings (and `append` does enforce sanitisation/escaping). This feature is not string interpolation (although it could also be used for string interpolation as a special case), and its function is completely different from that of StringBuilder. StringBuilder simply cannot do what this feature does regardless of your thoughts about the syntax, which may or may not be formed after actual experience.
> But what about the `}` after the expression? Who/what is escaping that?
You don't need to. `\` in Java means that the next character triggers some special interpretation, and `\{` means that the interpretation mode continues until the `}`. The closing curly bracket should require no more of a special treatment than the characters inside the curly brackets.
> Putting it in here feels wrong.
When you say "feels wrong" do you mean you've tried the feature for a while and ran into problems or that you simply fear that you might?
No, I am aware of the differences between StringBuilder and string templating. One of the most common usage is concatenation (e.g. toString() methods). Sometimes it's cleaner to use StringBuilder instead of + operator to do that. And templating will be mostly used for concatenation.
All I am saying is, it could be simpler. I read the full JEP before my first comment. I frequently do Python and did little bit of Kotlin before. I guess that's where all this is coming from.
Whether it will or won't, interpolation is not the reason for the feature, so clearly that's not the use case that should be prioritised, especially as it's been recognised as an exceptionally dangerous use-case. The starting point that we must in no way make string interpolation, which is known to be dangerous, any easier than using safer template processors.
This feature was created (among some other reasons) to solve the severe security problems created by string manipulation, not to make string concatenation -- which is already pretty easy -- easier. As the JEP explains, after a lot of thought the decision was not to offer string interpolation as a language feature and go for string templates instead. Saying that the feature doesn't accomplish well the thing it explicitly doesn't try to accomplish is really not saying much about the potential of this feature. Making string interpolation as easy as it could possibly be was not only not a goal of this feature, but the very thing it was designed to avoid given how dangerous that is.
On the other hand, consider that you can now safely embed HTML templates in Java code.
> I frequently do Python and did little bit of Kotlin before. I guess that's where all this is coming from.
In this case, as in many others, we studied what many other languages did, incorporated what's been learnt about code injection vulnerabilities, and did what we believe to be a marked improvement over other languages' features, at least as appropriate for Java's users. You may disagree, but a lot of thought has gone into the design by some of the world's most accomplished language designers as well as user testing, and so I don't think speculation trumps that. If further experience shows that we got it wrong, it can be fixed.
Absolutely nothing precluded extending the new syntax to swallowing / obviating the `.`.
In other words, security vulnerabilities due to string manipulation are a real and pretty serious problem that this feature aims to solve (or, at least alleviate). If the dot character also proves to be a real problem, which it hasn't yet, then that could be solved later.
The goal was getting something clean and friendly. Look at Python for example. Any similar solution would have made it both non-breaking (codes won't compile with unsupported version) and clean.