11

According to the tool PMD, the following is a bad practice:

String s = "" + 123; // bad 
String t = Integer.toString(456); // ok 


This is an inefficient way to convert any type to a `String`.

Why is it a bad thing to do?

George Stocker
  • 57,289
  • 29
  • 176
  • 237
corgrath
  • 11,673
  • 15
  • 68
  • 99
  • Apparently, for constants (static/final) "" + 123 is more efficient. For other values, using toString is more efficient. – corgrath Sep 02 '10 at 12:50
  • "Static/final" can be misleading. A field must be _both_ static and final to be considered a constant, and only for primitives and strings. (Local variables are never considered constant.) – C. K. Young Sep 02 '10 at 12:52
  • possible duplicate of [Is conversion to String using ("" + ) bad practice?](http://stackoverflow.com/questions/1572708/is-conversion-to-string-using-int-value-bad-practice) – McDowell Sep 02 '10 at 13:24

4 Answers4

22

It is inefficient, as it involves an unneeded string concatenation, thus the creation of one or two extra String objects - although I believe the JIT can optimize it away.

To me the bigger problem is that the code is less clear. Calling toString is a standard idiom, understandable to every Java developer (hopefully :-), so you should prefer this.

Péter Török
  • 114,404
  • 31
  • 268
  • 329
14
String s = "" + 123; // bad     
String t = Integer.toString(456);

Will be compiled to:

String s = "123";
String t = Integer.toString(456);

so: "" +123 is obvious slightly better! Checked with JAD

public static void main(String args[])
{
//    0    0:ldc1            #16  <String "123">
//    1    2:astore_1
//    2    3:sipush          456
//    3    6:invokestatic    #18  <Method String Integer.toString(int)>
//    4    9:astore_2
//    5   10:getstatic       #24  <Field PrintStream System.out>
//    6   13:new             #30  <Class StringBuilder>
//    7   16:dup
//    8   17:aload_1
//    9   18:invokestatic    #32  <Method String String.valueOf(Object)>
//   10   21:invokespecial   #38  <Method void StringBuilder(String)>
//   11   24:aload_2
//   12   25:invokevirtual   #41  <Method StringBuilder StringBuilder.append(String)>
//   13   28:invokevirtual   #45  <Method String StringBuilder.toString()>
//   14   31:invokevirtual   #48  <Method void PrintStream.println(String)>
//   15   34:return
}

EDIT:

For non-constant values:

int i = 123;
String s = (new StringBuilder()).append(i).toString();
String t = Integer.toString(i);
System.out.println((new StringBuilder(String.valueOf(s))).append(t).toString());

    public static void main(String args[])
    {
    //    0    0:bipush          123
    //    1    2:istore_1
    //    2    3:new             #16  <Class StringBuilder>
    //    3    6:dup
    //    4    7:invokespecial   #18  <Method void StringBuilder()>
    //    5   10:iload_1
    //    6   11:invokevirtual   #19  <Method StringBuilder StringBuilder.append(int)>
    //    7   14:invokevirtual   #23  <Method String StringBuilder.toString()>
    //    8   17:astore_2
    //    9   18:iload_1
    //   10   19:invokestatic    #27  <Method String Integer.toString(int)>
    //   11   22:astore_3
    //   12   23:getstatic       #32  <Field PrintStream System.out>
    //   13   26:new             #16  <Class StringBuilder>
    //   14   29:dup
    //   15   30:aload_2
    //   16   31:invokestatic    #38  <Method String String.valueOf(Object)>
    //   17   34:invokespecial   #44  <Method void StringBuilder(String)>
    //   18   37:aload_3
    //   19   38:invokevirtual   #47  <Method StringBuilder StringBuilder.append(String)>
    //   20   41:invokevirtual   #23  <Method String StringBuilder.toString()>
    //   21   44:invokevirtual   #50  <Method void PrintStream.println(String)>
    //   22   47:return
    }
stacker
  • 68,052
  • 28
  • 140
  • 210
  • 1
    I'm not sure I am following you. Did you prove that ""+123 is better than Integer.toString(123)? – corgrath Sep 02 '10 at 12:26
  • +1 for actually checking. Now what about object types rather than pod types? – Philip Potter Sep 02 '10 at 12:28
  • @corgrath since jad showed it's compiled to String s = "123"; it is converted during compile time into a string literal. – stacker Sep 02 '10 at 12:31
  • 3
    "" + 123 is a constant expression, which is evaluated already by the compiler to be "123". – jarnbjo Sep 02 '10 at 12:31
  • `"" + 123` becomes `"123"` because you're specifying a constant. Now try `"" + Math.random()` versus `String.valueOf(Math.random())`. – C. K. Young Sep 02 '10 at 12:33
  • @corgrath: Don't mind Philip, I think he meant primitive types, not POD types per se (which is a C++ concept). In C++, POD means "plain old data", which means (very roughly) that objects of such types have value semantics. (The real definition of POD type is rather more stringent than that.) – C. K. Young Sep 02 '10 at 12:34
  • Oh, ok. So x = 4+5; ""+x is also a constant expression, meaning same cost? – corgrath Sep 02 '10 at 12:35
  • @corgrath: Only if `x` is `static final`. – C. K. Young Sep 02 '10 at 12:36
  • So for non static finals, using toString is more efficient? – corgrath Sep 02 '10 at 12:42
  • @corgrath: For non-statics or non-finals, the constant optimisation described in this answer will not apply. – C. K. Young Sep 02 '10 at 12:48
  • 1
    @stacker: "so: "" +123 is obvious slightly better" better is subjective the only obvious is that it's faster. It's sacrificing readability for performance with no known performance issues that premature optimization which is usually considered bad – Rune FS Sep 02 '10 at 12:56
  • 2
    I think having this marked as the answer is misleading and unhelpful. As Chris Jester-Young points out, it's only faster in cases where the int is final. In order to produce better code, in cases where the int is final, you should have a corresponding string representation of that int as a string which is also final (this is what the compiler does automatically). `"" + 123` is not at all "better", it is equivalent to declaring a new static string with the value `"123"` and has nothing to do with the int `123`. – Nathan Sep 17 '12 at 01:33
6

It expands to "" + String.valueOf(yourObject) and thus does an unneeded concatenation. The concatenation involves allocating an extra string and doing an extra copy of the string's value.

jkff
  • 17,623
  • 5
  • 53
  • 85
  • 5
    and the tostring version clearly states the intend. "Convert this value to a string" – Rune FS Sep 02 '10 at 12:13
  • 1
    This is not strictly correct from a code generation point of view, so I will refrain from upvoting. It actually (for Java 6u20, which I tested with) expands to: `new StringBuilder().append("").append(yourObject).toString()`, assuming that `yourObject` is not constant. – C. K. Young Sep 02 '10 at 12:57
0
String s = "" + 123; // bad

The above code creates a temporary string, to combine "" and 123

Dead Programmer
  • 12,427
  • 23
  • 80
  • 112