views:

434

answers:

7

Is conversion to String in Java using

"" + <int value>

bad practice? Does it have any drawbacks compared to String.valueOf(...)?

Code example:

int i = 25;
return "" + i;

vs:

int i = 25;
return String.valueOf(i);

Update: (from comment)

And what about Integer.toString(int i) compared to String.valueOf(...)?

+16  A: 

I would always prefer the String.valueOf version: mostly because it shows what you're trying to do. The aim isn't string concatenation - it's conversion to a string, "the string value of i".

The first form may also be inefficient - depending on whether the compiler spots what you're doing. If it doesn't, it may be creating a new StringBuffer or StringBuilder and appending the value, then converting it to a string.

Funnily enough, I have an article about this very topic - written years and years ago; one of the first Java articles on my web site, IIRC.

Jon Skeet
+1 for "because it shows what you're trying to do"
Adam Paynter
A: 

Yes, it is IMHO a bad practice.

It would require to memory allocations (unless compiler and/or JIT optimize them). What's more, it will make less evident, what this code tries to do.

elder_george
+2  A: 

Regardless of any performance considerations I think the first variant is really ugly. IMHO it's a shame that this kind of "dynamic casting" is even possible in Java.

DR
+7  A: 

Definitely use String.valueOf(i).

Although I'm not sure of the optimizations on the compiler side, worst case scenario if you use "" + :

  1. "" creates a new empty string.
  2. "" + creates a StringBuilder (Java 1.5-16)
  3. "" is appended to the StringBuilder, then

In other words, there is a lot of overhead that occurs if you use string addition. This is why it is not recommended to use the + operator on strings in loops. In general, always use Boolean.valueOf, Integer.valueOf, String.valueOf... etc, when possible. You'll save both on memory and on overhead.

Malaxeur
"" doesn't create a new empty string on every iteration. There will be a single string for all the occurrences of "". But yes, unless the compiler catches it you'll end up with an extra StringBuilder.
Jon Skeet
The first empty quote will be interned, so there will only ever be one (this is a JLS thing, not just an optional optimization).
Yishai
The issue with + on strings in loops has nothing to do with this.
Michael Borgwardt
Ah, I wasn't aware that the literal was interned. I was under the assumption that unless you explicitly call .intern, no string literals are interned. Regardless, there's additional overhead on the internalizing + extra overhead of an empty string (for nothing) in this case... which we're all in agreement with.
Malaxeur
The issue with + on strings in loops has nothing to do with this.
Michael Borgwardt
The interning doesn't have any overhead on a per invocation basis - it's done on class load. That wouldn't bother me at all. It's the creation of a pointless StringBuilder etc that's the problem.
Jon Skeet
It's true that only one instance of the empty string will be created, but that's still one wasted creation of a string. Well, maybe in a non-trivial program you're going to create an empty string for something somewhere anyway.
Jay
A: 

Personally I dislike the style of "" + i, but that is really a preference/coding standards thing. Ideally the compiler would optimize those into equivalent code (although you would have to decompile to see if it actually does), but technically, without optimization, "" + i is more inefficient because it creates a StringBuilder object that wasn't needed.

Yishai
A: 

Right off the bat all I can think of is that in the your first example more String objects will be created than in the second example (and an additional StringBuilder to actually perform the concatenation).

But what you are actualy trying to do is create a String object from a int not concatenate a String with an int, so go for the:

String.valueOf(...);

option,

So yes your first option is bad practice!

Ron Tuffin
`Integer.valueOf(int i)` returns an `Integer`, not a `String`
Kip
Thanks Kip. In my haste to beat Skeet, I mistyped it. fixed.
Ron Tuffin
+7  A: 

There is also Integer.toString(int i), which gives you the option of getting the string as a hex value as well (by passing a second param of 16).

Edit I just checked the source of String class:

public static String valueOf(int i) {
  return Integer.toString(i, 10);
}

And Integer class:

public static String toString(int i, int radix) {
  if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
    radix = 10;

  /* Use the faster version */
  if (radix == 10) {
    return toString(i);
  }
  ...

If you call String.valueOf(i), it calls Integer.toString(i, 10), which then calls Integer.toString(i).

So Integer.toString(i) should be very slighty faster than String.valueOf(i), since you'd be cutting out two function calls. (Although the first function call could be optimized away by the compiler.)

Of course, a readability argument could still be made for String.valueOf(), since it allows you to change the type of the argument (and even handles nulls!), and the performance difference is negligible.

Kip
+1 for checking the source and reporting back. Admittedly, may be considered premature optimization, but good information nonetheless.
RHSeeger