views:

199

answers:

4

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?

+6  A: 

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
and the tostring version clearly states the intend. "Convert this value to a string"
Rune FS
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.
Chris Jester-Young
+13  A: 

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
Code transparency is crucial thing for me.
Bart
Code clarity should always go before micro optimizations.
JesperE
+7  A: 
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
I'm not sure I am following you. Did you prove that ""+123 is better than Integer.toString(123)?
corgrath
+1 for actually checking. Now what about object types rather than pod types?
Philip Potter
What are pod types?
corgrath
@corgrath since jad showed it's compiled to String s = "123"; it is converted during compile time into a string literal.
stacker
"" + 123 is a constant expression, which is evaluated already by the compiler to be "123".
jarnbjo
`"" + 123` becomes `"123"` because you're specifying a constant. Now try `"" + Math.random()` versus `String.valueOf(Math.random())`.
Chris Jester-Young
@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.)
Chris Jester-Young
Oh, ok. So x = 4+5; ""+x is also a constant expression, meaning same cost?
corgrath
@corgrath: Only if `x` is `static final`.
Chris Jester-Young
So for non static finals, using toString is more efficient?
corgrath
@corgrath: For non-statics or non-finals, the constant optimisation described in this answer will not apply.
Chris Jester-Young
@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
do not perform micro optimization ,learnt from jon skeet
Suresh S
A: 
String s = "" + 123; // bad

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

Suresh S
Not so simple. See stacker's answer. If instead of 123 you have a non-constant value, then you'd be correct.
Chris Jester-Young