279

String building in Java confounds me. I abhore doing things like:

url += "u1=" + u1 + ";u2=" + u2 + ";u3=" + u3 + ";u4=" + u4 + ";";
url += "x=" + u1 + ";y=" + u2 + ";z=" + u3 + ";da1=" + u4 + ";";
url += "qty=1;cost=" + orderTotal + ";ord=" + orderId + "?";

Or, using StringBuilder, something like this:

    url.append("u1=");
    url.append(u1);
    url.append(";u2=");
    url.append(u2);
    url.append(";u3=");
    url.append(u3);
    url.append(";u4=");
    url.append(u4);
    url.append(";");
    url.append("x=");
    url.append(u1);
    url.append(";y=");
    url.append(u2);
    url.append(";z=");
    url.append(u3);
    url.append(";da1=");
    url.append(u4);
    url.append(";");
    url.append("qty=1;");
    url.append("cost=");
    url.append(orderTotal);
    url.append(";ord=");
    url.append(orderId);
    url.append("?");

SURELY I'm missing something. There has GOT to be a better way. Something like:

Instead of:

urlString += "u1=" + u1 + ";u2=" + u2 + ";u3=" + u3 + ";u4=" + u4 + ";";

do:

urlString += Interpolator("u1=%s;u2=%s;u3=%s;u4=%s;", u1, u2, u3, u4);

or:

urlStringBuilder.append(Interpolator("u1=%s;u2=%s;u3=%s;u4=%s;", u1, u2, u3, u4));
kodliber
  • 69
  • 1
  • 7
cmcculloh
  • 47,596
  • 40
  • 105
  • 130

5 Answers5

435

If you're using Java 5 or higher, you can use String.format:

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

See Formatter for details.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 6
    If you care about performance, you should avoid `String.format`. [Check performance comparison among Java string interpolation from redfin](https://redfin.engineering/java-string-concatenation-which-way-is-best-8f590a7d22a8). – Miae Kim Oct 22 '19 at 22:18
  • 67
    @MiaeKim: It's entirely possible to *care* about performance without micro-optimizing every line of code. I care a lot about performance in Noda Time - but I'm perfectly happy to do string formatting when throwing an exception, for example. – Jon Skeet Oct 23 '19 at 05:28
  • 2
    Like you mentioned Noda Time, it is totally depends on use cases. If there's a case when you create huge number of logs, String.format is can affect as well. This comment is just for reference. – Miae Kim Oct 23 '19 at 19:07
  • 39
    @MiaeKim: Then I think it should be more closely scoped. "For pieces of code where performance is critical" is more helpful than "If you care about performance" IMO. Who's going to say they, as a developer, don't care about performance? It's a matter of judging where to sacrifice readability for the sake of performance. – Jon Skeet Oct 24 '19 at 06:25
  • 5
    Since Java 15 you can use `formatted` method directly on string instance which will do the same as `String.format` method. E.g `"Print %s".formatted("text")` – Kovsharov Dec 10 '21 at 08:25
  • @Kovsharov I think your comment is the best way of string interpolation in java at the moment. Thanks – Andrew Taran Aug 15 '22 at 17:17
139

Note that there is no variable interpolation in Java. Variable interpolation is variable substitution with its value inside a string. An example in Ruby:

#!/usr/bin/ruby

age = 34
name = "William"

puts "#{name} is #{age} years old"

The Ruby interpreter automatically replaces variables with its values inside a string. The fact, that we are going to do interpolation is hinted by sigil characters. In Ruby, it is #{}. In Perl, it could be $, % or @. Java would only print such characters, it would not expand them.

Variable interpolation is not supported in Java. Instead of this, we have string formatting.

package com.zetcode;

public class StringFormatting 
{
    public static void main(String[] args) 
    {
        int age = 34;
        String name = "William";

        String output = String.format("%s is %d years old.", name, age);
    
        System.out.println(output);
    }
}

In Java, we build a new string using the String.format() method. The outcome is the same, but the methods are different.

See http://en.wikipedia.org/wiki/Variable_interpolation

Edit As of 2019, JEP 326 (Raw String Literals) was withdrawn and superseded by multiple JEPs eventually leading to JEP 378: Text Blocks delivered in Java 15.

A text block is a multi-line string literal that avoids the need for most escape sequences, automatically formats the string in a predictable way, and gives the developer control over the format when desired.

However, still no string interpolation:

Non-Goals: … 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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Jan Bodnar
  • 10,969
  • 6
  • 68
  • 77
  • 71
    I wonder why interpolated strings are not supported/introduced into the Java language. It seems like a very useful feature. – Hervian Dec 23 '16 at 08:10
  • 3
    Java Strings are immutable, can't be changed, so there's no "insert XXX into String YYY." A simplified syntax, such as the Ruby #{}, with String.format() semantics (i.e., create a new string) would respect String immutability, but run afould of other core Java design constraints. – jackr May 16 '17 at 20:47
  • 43
    @jackr Python's strings are immutable too. However "string interpolation" can be seen more as a way of constructing one string, than a way of editing an existing one. It was not introduced in java most likely because of other priorities. It exists in C# and many other languages more java-like. – vlad-ardelean Aug 26 '17 at 08:45
  • 37
    @jackr C# treats strings very similarly to java, and it has interpolated strings – Austin_Anderson Oct 27 '17 at 17:47
  • 4
    @jackr, it would be great if we had this feature at it significantly improves code readability. On the issue of immutability, strongly I believe that this can be done at compile time; other languages have done it – Peter Chaula Jan 28 '19 at 04:57
  • 1
    Ruby systems aren't supposed to last 18 years, Java does. – JBarros35 Nov 17 '20 at 11:21
  • 1
    little sugar syntax: You can use `System.out.printf("%s is %d years old.", name, age);` instead `String output = String.format("%s is %d years old.", name, age); System.out.println(output);` – stanimirsp Feb 17 '21 at 21:49
47

Just to add that there is also java.text.MessageFormat with the benefit of having numeric argument indexes.

Appending the 1st example from the documentation

int planet = 7;
String event = "a disturbance in the Force";

String result = MessageFormat.format(
    "At {1,time} on {1,date}, there was {2} on planet {0,number,integer}.",
    planet, new Date(), event);

Result:

At 12:30 PM on Jul 3, 2053, there was a disturbance in the Force on planet 7.
Jimmy Kane
  • 16,223
  • 11
  • 86
  • 117
  • 34
    **WARNING**: MessageFormat is orders of magnitude slower than string concatenation or `String.format()`. – ccpizza Oct 14 '16 at 15:12
  • 4
    This should not come as much of an advantage if you know how to use `String.format()`, namely with the `n$` part of the format identifiers. – Adowrath Nov 21 '16 at 16:14
  • 6
    As @Adowrath pointed out, you can reference indices with: `String.format( "At %2$tT on %2$tD, there was %3$s on planet %1$d.", planet, new Date(), event);` [See here for more formatting options](https://dzone.com/articles/java-string-format-examples) – ecoe Feb 04 '18 at 00:08
  • @ecoe but definitely more hard to remember at least for me – Jimmy Kane Sep 12 '18 at 16:26
20

String.format() to the rescue!!

unholysampler
  • 17,141
  • 7
  • 47
  • 64
  • Avoid `String.format()` as possible, here is why: https://redfin.engineering/java-string-concatenation-which-way-is-best-8f590a7d22a8 – Miae Kim Feb 19 '19 at 19:22
  • 10
    That article does not say "avoid `String.format`". I'm not convinced it even had more cons than any of the other methods it listed. – GreenAsJade Mar 11 '19 at 00:39
-1

You can use Kotlin, the Super (cede of) Java for JVM, it has a nice way of interpolating strings like those of ES5, Ruby and Python.

class Client(val firstName: String, val lastName: String) {
    val fullName = "$firstName $lastName"
}
LEMUEL ADANE
  • 8,336
  • 16
  • 58
  • 72
  • 82
    Although kotlin is nice (I use it a lot!) I'm not sure how relevant this is to the question, which specifies java. – Restioson Aug 03 '17 at 15:30
  • 3
    Yes, it still is. There is a Kotlin-Java inter-operability. It means you can call Kotlin code in Java code and vice versa. – LEMUEL ADANE Oct 24 '17 at 13:09
  • 33
    Just because it is fully interoperable doesn't mean you'd necessarily want to use it in your java project – Restioson Oct 25 '17 at 07:34
  • 2
    Yeah, but its a java users' prerogative. :) – LEMUEL ADANE Nov 01 '17 at 03:51
  • 4
    It's a Java user's prerogative to use a completely different programming language? This is not a helpful answer. It might as well be in Ruby for all the good it does Java developers. – DavidS Dec 18 '20 at 18:10