String interpolation in Java 14 or 15
Asked Answered
P

6

28

Since I am using Java 14 and 15 preview features. Trying to find the string interpolation in java.

The closest answer I found is

String.format("u1=%s;u2=%s;u3=%s;u4=%s;", u1, u2, u3, u4)

Since the answer which I got from lots fo references are old answers asked 4,5 years ago. Is there any update on the string interpolation in java 11,12,13,14,15 equivalent to C#

string name = "Horace";
int age = 34;
Console.WriteLine($"Your name is {name} and your age {age}");

EDIT: JEP 430, which covers this and much more, has been proposed to target JDK 21.

Pencel answered 24/8, 2020 at 10:27 Comment(19)
Looks like Java doesn't have time for such frivolous features. Some languages had it from day 1, others have even enhanced it in recent releases. But looks like Java always knows better than day to day developer productivity :)Stake
Why do you believe Java is adding String Interpolation support? --- Are you perhaps confusing Interpolation with the Text Block support being added (preview in Java 13 and 14, final in Java 15)? Note that JEP 378: Text Blocks specifically says: "Text blocks do not directly support string interpolation. Interpolation may be considered in a future JEP. In the meantime, the new instance method String::formatted aids in situations where interpolation might be desired."Millwork
@ernest_k, it's not as clear of a cut to add language features to 20+ year old language that's widely in use. Such "simple" feature as text blocks caused a lot of debates (look up that JEP's history) - added inline interpolation will cause a storm. Because everyone has their favorite pet "developer productivity" feature from some recent language, and everyone's favorite feature also isn't compatible with everyone else's favorite feature.Theocracy
@M.Prokhorov Absolutely, and I'm sure Java's design principles are sound (like... you should prefer features that add real value and that you're going to be willing to support in a future, backward compatible version, as I saw somewhere). One fact, though: when developer productivity is up for evaluation, I guess, usually those other guiding principles win (Python is older than Java and widely adopted, but it gets such changes - that's maybe because they put a limit to backward compatibility, etc.). Not trying to be presumptuous, that's just some superficial thinking/speculation.Stake
@Stake Developer productivity is important even in Java, a good example of this is the recently added pattern matching for instanceof feature (avoid those redundant looking casts). It might seem like something like this is such a small thing to add, but it takes months/years to work out all the details, maybe to eventually decide that a feature should not be added after all. String interpolation in particular is just not at the top of the TODO list currently.Fusionism
@Stake I’m wondering, how much productivity you really gain, by writing $"Your name is {name} and your age {age}" instead of "Your name is "+name+" and your age "+ageCraniometer
@Craniometer valid question, but I'm afraid it's too specific for a comment intended to be general. And, of course, I haven't measured it (assuming I can). My comment is not that original, everyone knows that Java doesn't prioritize "improvements" that make it easier to code in the language (boilerplate is perhaps too characteristic of Java, and is one of the things that make it dreadful for many - and I'm not one of those). And to your question, $"..." is definitely more readable & less bug-prone than ".." + "..", let alone String.format("..", name, age). +Interpolation is jut one of manyStake
@Stake “less bug-prone” heavily depends on how the hypothetical feature handles dangling { or } characters (or what I need to do when I want to insert literal { or } characters) or identifiers that do not match variables or whether the compiler or the runtime is supposed to resolve those identifiers. For "constant"+variable+"…", it’s clear that I get response at compile time (or immediately while typing when using an IDE). Can’t agree that Java doesn't prioritize productivity, I mean, name the last Java version that didn’t introduce language improvements in that regard…Craniometer
@Craniometer I don't want to stretch this too much; you make a good point about concatenation with +. It was more about String.format vs native string interpolation (you know what I mean). And I don't want my remarks to be construed as radical; Java is getting positive changes and I know that designers are good at picking the right features... Yet that doesn't change the fact that devs would have a very long wish-list of nice-to-haves. And I don't think it's merely because of low priority, but because of conflict (current and future backward compatibility, etc.)Stake
@birgersp unless you come up with a surprising reason why "Age: $age." is so much better than the proposed "Age: {age}.", my opinion does not change.Craniometer
@birgersp there is no point. Except you can name a reason why it should be better.Craniometer
@Craniometer Sorry I mixed some examples here. Let me correct myself; $"Age: {age}." is more productive than "Age: " + age + ".". Even with just 1 variable it is shorter and sweeter. Now imagine strings where you add 8, 10, 15(!) variables into it. Java would benefit from implementing string interpolation like C# (and other langauges) has.Canotas
As to the "reasoning" why it is productive I won't bother explain it to you. It is like asking why is it "better" to write 3x5 when you can just write 3+3+3+3+3?Canotas
@Canotas seriously? You want to argue that saving just one character in source code, plus some ignorable white-space that you apparently inserted to make the difference look more dramatic, deserves a new language feature? In the example of the previous comment, $"Your name is {name} and your age {age}" vs "Your name is "+name+" and your age "+age, there is no difference at all. That feature will never compensate the productivity you already lost while writing such comments.Craniometer
Nearly all formatters add space before and after operators. So :"+text+". would be formatted to :" + text + ".. So there are your extra characters. String interpolation like C# has should be added to Java because it has the same result, with less code without hurting readability. In fact people would argue that it is even more readable but that would perhaps be too subjective. Again, your example has 1 variable. But what about strings with e.g. 5 variables? Do you still not see how it would be more productive?Canotas
+ chaining method is a crappy method for a crappy codeGopherwood
I was looking for an answer on why Java hasn't yet added string interpolation. Is there any technical difficulty? Or they just don't agree on using curly braces vs dollar signs? I guess that they could go the JavaScript way and add template literals. It is already proven, developers know it very well, and it's a non-breaking change because the back-quote character ` is not currently used in the language.Myelitis
Related; https://mcmap.net/q/110163/-string-replacement-in-java-similar-to-a-velocity-template/8583692Pastern
@Canotas you didn’t @ me, so I didn’t notice your response. My answer today would be the same as back then, regarding the savings, even considering additional white-space and more variables. In fact, it looks weird to me, to configure formatters to insert additional white-space for readability, followed by arguing that the alternative, denser syntax is more readable. However, seeing what they’ll do with JEP 430, I changed my mind. String interpolation is indeed a useful thing, but not because you might save typing. Solving the operator precedence issue, allow sanitizing arguments, etc…Craniometer
M
47

There is something slightly closer; an instance version of String::format, called formatted:

String message = "Hi, %s".formatted(name);

It is similar to String::format, but is more friendly to use in chained expressions.

Mercantilism answered 24/8, 2020 at 21:56 Comment(2)
It seems to be widely overlooked, how expensive java.util.Formatter is. Otherwise, methods like Optional.toString() were not implemented as String.format("Optional[%s]", value) where a simple "Optional[" + value + "]" would do. In a fresh environment, this unnecessary use of format triggers the loading of 165 formerly unused classes, giving a hint of the involved components. Using a framework for locale sensitive data formatting into arbitrary I/O sinks, just for something that boils down to ordinary string concatenation, is like flying with the Falcon X to the supermarket.Craniometer
Is it possible to bring this feature in upcoming Java versions?Akene
A
11

To my knowledge, there are no updates in the standard java libraries regarding such kind of string formatting.

In other words: you are still "stuck" with either using String.format() and its index based substitution mechanism, or you have to pick some 3rd party library/framework, such as Velocity, FreeMarker, ... see here for an initial overview.

Aborn answered 24/8, 2020 at 10:31 Comment(1)
Third option: write "Your name is "+name+" and your age "+age. Wouldn’t work for a dynamic string, but capturing all variables in scope, just because they might be referenced in the format string, is not the way of a compiled language.Craniometer
A
2

You can use Java's String Templates feature. It is described in JEP 430, and it appears in JDK 21 as a preview feature. Here is an example use:

string name = "Horace";
int age = 34;
System.out.println(STR."Your name is {name} and your age {age}");
Albric answered 5/8, 2023 at 17:11 Comment(0)
C
1

There is no built-in support for that currently, but Apache Commons Text's StringSubstitutor can be used.

import org.apache.commons.text.StringSubstitutor;
import java.util.HashMap;
import java.util.Map;
// ...
Map<String, String> values = new HashMap<>();
values.put("animal", "quick brown fox");
values.put("target", "lazy dog");
StringSubstitutor sub = new StringSubstitutor(values);
String result = sub.replace("The ${animal} jumped over the ${target}.");
// "The quick brown fox jumped over the lazy dog."

This class supports providing default values for variables.

String result = sub.replace("The number is ${undefined.property:-42}.");
// "The number is 42."

To use recursive variable replacement, call setEnableSubstitutionInVariables(true);.

Map<String, String> values = new HashMap<>();
values.put("b", "c");
values.put("ac", "Test");
StringSubstitutor sub = new StringSubstitutor(values);
sub.setEnableSubstitutionInVariables(true);
String result = sub.replace("${a${b}}");
// "Test"
Crosslegged answered 19/4, 2021 at 1:26 Comment(1)
There are two imports missing import java.util.HashMap; import java.util.Map; also this import might be useful import org.apache.commons.lang3.StringUtils;Adamandeve
Q
1

You can also use MessageFormat like this (Java 5.0 or later)

MessageFormat.format("Hello {0}, how are you. Goodbye {0}",userName);

Very nice

Quintain answered 28/1, 2022 at 14:17 Comment(3)
@user16320675, really, really, i got to know about MessageFormat today, and it mentioned in terms of java 15 so i decided it appeared in java 15Quintain
@user16320675 i have read this one - docs.oracle.com/en/java/javase/15/docs/api/java.base/java/text/… Its titled in google as - MessageFormat (Java SE 15 & JDK 15), so i decided that it's not available in earlier versionsQuintain
Well, all pages of the JDK 15 API documentation have the “JDK 15 API” title but you only need to scroll through the very page you’ve linked to find Since: 1.1 So it’s neither JDK 15 nor Java 5.0 that introduced this class but Java 1.1 or, in other words, this feature exists almost since day one.Craniometer
A
-2

Looks like nice C#-style interpolation is not available in these Java versions. Why we need this - to have nice and readable lines of code dumping text to Log files.

Below is sample code that works (there is commented org.apache.commons.lang3.StringUtils which at some point of writing was required but later it was not) - it was dropping ClassNotFound or other NotFoundException - I have not investigated it.

The StringSubstitutor might be later packed in something nicer that will make it easier to use for Log message dumping

package main;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.text.*;
//import org.apache.commons.lang3.StringUtils;

public class Main {

    public static void main(String[] args) {
        System.out.println("Starting program");
        
        var result =  adding(1.35,2.99);

        Map<String, String> values = new HashMap<>();
        values.put("logMessageString", Double.toString(result) );

        StringSubstitutor sub = new StringSubstitutor(values);
        sub.setEnableSubstitutionInVariables(true);
        String logMessage = sub.replace("LOG result of adding: ${logMessageString}");

        System.out.println(logMessage);
        System.out.println("Ending program");
         
    }
    // it can do many other things but here it is just for prcoessing two variables 
    private static double adding(double a, double b) {
        return a+b;
    }

}
Adamandeve answered 11/8, 2021 at 15:8 Comment(1)
Java logging frameworks have this sort of stuff built in.Eller

© 2022 - 2024 — McMap. All rights reserved.