<div dir="ltr">Hello list.<div><br></div><div>First, I welcome suggestions and feedback on what kind of information is useful to contribute to the topic of string templates in Java.</div><div><br></div><div>I have been developing in Python for about the last two years, but am now starting a new Java project for the first time in a while. And even though Python is full of cool features that would be nice to have in Java, I understand that just because a feature is cool in one language, "coolness" is not the only consideration in deciding  whether or not to adopt it in another language.</div><div><br></div><div>I just want to give my personal experience in string handling in Python, specifically "f-strings" or  "formatted string literals". These are string literals but they can capture values of variables and methods defined in the current scope. You prefix the string literal with the letter 'f' (for format). E.g.,</div><div><br></div><div>num_hamburgers = 12<br>print( f"I have eaten {num_hamburgers} today at {time.now}.")</div><div><br></div><div>As with printf() and similar string display methods, there are a plethora of ways to format each replacement field. This isn't a live template - the replacement fields capture the value at the point they are defined in the runtime and thereafter have the same string value. </div><div><br></div><div>You can also store the template in a regular string and manually call a format method on it as your data changes as you can in Java. E.g.,</div><div><br></div><div><div style="background-color:rgb(30,31,34);color:rgb(188,190,196)"><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt">template: <span style="color:rgb(136,136,198)">str </span>= <span style="color:rgb(106,171,115)">"Hello {name}, it's now {time} o'clock"<br></span>name: <span style="color:rgb(136,136,198)">str </span>= <span style="color:rgb(106,171,115)">"Rob"<br></span>time: <span style="color:rgb(136,136,198)">int </span>= <span style="color:rgb(42,172,184)">12<br></span><span style="color:rgb(136,136,198)">print</span>(<span style="color:rgb(106,171,115)">"template: " </span>+ template)<br><span style="color:rgb(136,136,198)">print</span>(<span style="color:rgb(106,171,115)">"formated: " </span>+ template.format(<span style="color:rgb(170,73,38)">name</span>=name, <span style="color:rgb(170,73,38)">time</span>=time))<br><span style="color:rgb(136,136,198)">print</span>(<span style="color:rgb(106,171,115)">"f-string: " </span>+ <span style="color:rgb(106,171,115)">f"Hello </span><span style="color:rgb(207,142,109)">{</span>name<span style="color:rgb(207,142,109)">}</span><span style="color:rgb(106,171,115)">, it's now </span><span style="color:rgb(207,142,109)">{</span>time<span style="color:rgb(207,142,109)">}</span><span style="color:rgb(106,171,115)"> o'clock"</span>)<br><br><span style="color:rgb(122,126,133)"># output:<br></span><span style="color:rgb(122,126,133)"># template: Hello {name}, it's now {time} o'clock<br></span><span style="color:rgb(122,126,133)"># formated: Hello Rob, it's now 12 o'clock<br></span><span style="color:rgb(122,126,133)"># f-string: Hello Rob, it's now 12 o'clock</span></pre></div></div><div><br></div><div>Using format() behaves essentially identical to what Java has. But the simplicity of the f-string for capturing state really does increase my productivity in a meaningful way.</div><div><br></div><div>In my last project I used f-strings for two primary use cases.</div><div>1. Debugging information during development</div><div>2. Formal representation of an object's state in a "toString()" context. </div><div><br></div><div>I use the first case far more often. And yes I know how to use a debugger. :) I have just found that in many (most) cases, a few strategic println() or <a href="http://logger.info">logger.info</a>() statements are perfectly adequate for the task. These have a short lifecycle, sometimes existing only for the 5 minutes of debugging to identify a problem, or perhaps a little longer as scaffolding until my code solidifies and has the proper exceptions and logging handling in place. And for these cases, which occur every day in my life, the f-string format is much more helpful and less error prone than the current String format() method. The problem is that it is very easy to have a mismatch of arguments and format specifiers in Java, which results in me having to first debug my debugging! And reading such expressions also imposes a cognitive load that I do not feel with f-strings. </div><div><br></div><div>A simple non-trivial example:<br>```Java<br>String name = "Alice";<br>int age = 5;<br>double score = 93.456;<br>int rank = 2;<br><br>String template = "Name: %1$-10s | Age: %2$02d | Score: %3$07.2f | Rank: #%4$03d";<br>String result = String.format(template, name, age, score, rank);<br>System.out.println(result);<br></div><div>```</div><div><br></div><div>```Python</div><div>name = "Alice"<br>age = 5<br>score = 93.456<br>rank = 2<br><br>result = f"Name: {name:<10} | Age: {age:02} | Score: {score:07.2f} | Rank: #{rank:03}"<br>print(result)<br></div><div>```</div><div>I find it easier to scan the f-string than the equivalent Java formatted string.</div><div><br></div><div><br></div><div>Now, here's a real-world example of code I am porting from Python to Java, as part of a JSON pretty-printer. In Python, in a particular context where I am displaying formatted keys (kf) and values (vf) of a Map member: indent_str is a string of blank spaces to align the key:value horizontally. </div><div><br></div><div>Python:</div><div><br></div><div><div style="background-color:rgb(30,31,34);color:rgb(188,190,196)"><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><span style="color:rgb(106,171,115)">f"</span><span style="color:rgb(207,142,109)">{</span>indent_str<span style="color:rgb(207,142,109)">}{</span>OPEN_BRACE<span style="color:rgb(207,142,109)">}{</span>SPACE<span style="color:rgb(207,142,109)">}{</span>kf<span style="color:rgb(207,142,109)">}{</span>COLON<span style="color:rgb(207,142,109)">}{</span>SPACE<span style="color:rgb(207,142,109)">}{</span>vf<span style="color:rgb(207,142,109)">}{</span>SPACE<span style="color:rgb(207,142,109)">}{</span>CLOSE_BRACE<span style="color:rgb(207,142,109)">}</span><span style="color:rgb(106,171,115)">"</span></pre><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><br></pre></div></div><div>the variables here are indent_str, kf, and vf, and the rest are constants. Using constants instead of literal characters has several benefits that most developers should understand. I also appreciate the larger signal-to-noise ratio that the constants display over inline characters.</div><div><br></div><div>In Java, my first attempt to duplicate this was hilarious:</div><div><br></div><div><div style="background-color:rgb(30,31,34);color:rgb(188,190,196)"><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><span style="color:rgb(106,171,115)">"%s%s%s%s%s%s%s%s%s"</span>.formatted(indentString,<span style="color:rgb(199,125,187);font-style:italic">OPEN_BRACE</span>, <span style="color:rgb(199,125,187);font-style:italic">SPACE</span>, kf, <span style="color:rgb(199,125,187);font-style:italic">COLON</span>, <span style="color:rgb(199,125,187);font-style:italic">SPACE</span>, vf, <span style="color:rgb(199,125,187);font-style:italic">SPACE</span>, <span style="color:rgb(199,125,187);font-style:italic">CLOSE_BRACE</span>);</pre><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><br></pre></div></div><div>Uhm, is that 8, or 9, or 10 %s ? hmm...</div><div><br></div><div>So after some refactoring I ended up with this:</div><div><div style="background-color:rgb(30,31,34);color:rgb(188,190,196)"><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><span style="color:rgb(106,171,115)">"%s{ %s: %s }"</span>.formatted( indentString, kf, vf )</pre><pre style="font-family:"JetBrains Mono",monospace;font-size:9.8pt"><br></pre></div></div><div>bye-bye constants, you're as useful to me as a 4-assed monkey. (South Park reference...)</div><div><br></div><div>Is this "just as good?" Eh. Did I add an extra space somewhere? Did I forget a brace? Or did I add an extra one? And if I someday need to add a new argument, I need to add something in two places, and manually make sure to coordinate those.... sigh.</div><div><br></div><div>So that's my contribution to the topic for the day.</div><div><br></div><div>Am I just re-hashing obvious things that everyone knows about already?</div><div><br></div><div> - Rob</div><div><br></div><div><br></div></div>