780

I'm working on a project where all conversions from int to String are done like this:

int i = 5;
String strI = "" + i;

I'm not familiar with Java.

Is this usual practice or is something wrong, as I suppose?

Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
Denis Palnitsky
  • 18,267
  • 14
  • 46
  • 55

20 Answers20

981

Normal ways would be Integer.toString(i) or String.valueOf(i).

The concatenation will work, but it is unconventional and could be a bad smell as it suggests the author doesn't know about the two methods above (what else might they not know?).

Java has special support for the + operator when used with strings (see the documentation) which translates the code you posted into:

StringBuilder sb = new StringBuilder();
sb.append("");
sb.append(i);
String strI = sb.toString();

at compile-time. It's slightly less efficient (sb.append() ends up calling Integer.getChars(), which is what Integer.toString() would've done anyway), but it works.

To answer Grodriguez's comment: ** No, the compiler doesn't optimise out the empty string in this case - look:

simon@lucifer:~$ cat TestClass.java
public class TestClass {
  public static void main(String[] args) {
    int i = 5;
    String strI = "" + i;
  }
}
simon@lucifer:~$ javac TestClass.java && javap -c TestClass
Compiled from "TestClass.java"
public class TestClass extends java.lang.Object{
public TestClass();
  Code:
   0:    aload_0
   1:    invokespecial    #1; //Method java/lang/Object."<init>":()V
   4:    return

public static void main(java.lang.String[]);
  Code:
   0:    iconst_5
   1:    istore_1

Initialise the StringBuilder:

   2:    new    #2; //class java/lang/StringBuilder
   5:    dup
   6:    invokespecial    #3; //Method java/lang/StringBuilder."<init>":()V

Append the empty string:

   9:    ldc    #4; //String
   11:    invokevirtual    #5; //Method java/lang/StringBuilder.append:
(Ljava/lang/String;)Ljava/lang/StringBuilder;

Append the integer:

   14:    iload_1
   15:    invokevirtual    #6; //Method java/lang/StringBuilder.append:
(I)Ljava/lang/StringBuilder;

Extract the final string:

   18:    invokevirtual    #7; //Method java/lang/StringBuilder.toString:
()Ljava/lang/String;
   21:    astore_2
   22:    return
}

There's a proposal and ongoing work to change this behaviour, targetted for JDK 9.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
SimonJ
  • 21,076
  • 1
  • 35
  • 50
257

It's acceptable, but I've never written anything like that. I'd prefer this:

String strI = Integer.toString(i);
duffymo
  • 305,152
  • 44
  • 369
  • 561
  • 103
    I prefer the String.valueOf approach, as you can use the exact same call for any type. – Jon Skeet Nov 05 '10 at 11:17
  • 1
    NumberFormatter would be a better approach – Kasturi Nov 05 '10 at 13:47
  • A good answer, Kasturi. I'd post it as something more than a comment. – duffymo Nov 05 '10 at 14:24
  • 2
    Sorry for my ignorance, but wouldn't this use the current culture? I'm coming form a .NET background BTW. – Ε Г И І И О Jul 02 '13 at 18:24
  • 3
    For an integer, there's no culture-specific stuff being used by default (there's no decimal or thousands separator at all). That's what `NumberFormatter` is for. You can use formats like `NumberFormat.getInstance(Locale.FRENCH)`. – Kat Aug 17 '15 at 20:25
115

It's not a good way.

When doing conversion from int to string, this should be used:

int i = 5;
String strI = String.valueOf(i);
darioo
  • 46,442
  • 10
  • 75
  • 103
  • 7
    1. You ask for the empty string; 2. You ask for concatenation; 3. as you do not have a string, you will finally convert your int into string. The solution of daridoo avoid the first steps. – Nicolas Nov 05 '10 at 14:24
  • does `int i` get boxed to an `Integer` before getting added to the `String strI`? – Kevin Meredith Oct 31 '14 at 15:08
  • 1
    @KevinMeredith, no, it doesn't. You'd be actually calling `StringBuilder.append(int)` (and `StringBuilder` has an `append` method for all the primitive types). – Kat Aug 17 '15 at 20:28
61

It's not only the optimization1. I don't like

"" + i

because it does not express what I really want to do 2.

I don't want to append an integer to an (empty) string. I want to convert an integer to string:

Integer.toString(i)

Or, not my prefered, but still better than concatenation, get a string representation of an object (integer):

String.valueOf(i)

1. For code that is called very often, like in loops, optimization sure is also a point for not using concatenation.

2. this is not valid for use of real concatenation like in System.out.println("Index: " + i); or String id = "ID" + i;

user85421
  • 28,957
  • 10
  • 64
  • 87
  • 3
    The people who are talking about performance in this context are a distraction. Far, far, far, far, far, far more important is _readability_. – Brian Goetz Mar 29 '20 at 14:28
23

A lot of introductory University courses seem to teach this style, for two reasons (in my experience):

  • It doesn’t require understanding of classes or methods. Usually, this is taught way before the word “class” is ever mentioned – nor even method calls. So using something like String.valueOf(…) would confuse students.

  • It is an illustration of “operator overloading” – in fact, this was sold to us as the idiomatic overloaded operator (small wonder here, since Java doesn’t allow custom operator overloading).

So it may either be born out of didactic necessity (although I’d argue that this is just bad teaching) or be used to illustrate a principle that’s otherwise quite hard to demonstrate in Java.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
16

The expression

"" + i

leads to string conversion of i at runtime. The overall type of the expression is String. i is first converted to an Integer object (new Integer(i)), then String.valueOf(Object obj) is called. So it is equivalent to

"" + String.valueOf(new Integer(i));

Obviously, this is slightly less performant than just calling String.valueOf(new Integer(i)) which will produce the very same result.

The advantage of ""+i is that typing is easier/faster and some people might think, that it's easier to read. It is not a code smell as it does not indicate any deeper problem.

(Reference: JLS 15.8.1)

Andreas Dolk
  • 113,398
  • 19
  • 180
  • 268
  • 3
    Your "equivalent" statement isn't equivalent. Even if calling `String.valueOf` required boxing `i` (it doesn't, as there is an overload that accepts an `int`), it wouldn't use `new Integer(i)`, it would use `Integer.valueOf(i)`. But it really doesn't do any of this. It does `new StringBuilder().append("").append(i).toString()`, as SimonJ's answer notes. StringBuilder has its own logic for turning a the primitive int `i` into a String. – Mark Peters Nov 05 '10 at 14:44
  • 4
    The part about the code smell is right though; code smell is the wrong term here. So I'll take off the downvote. – Mark Peters Nov 05 '10 at 14:47
  • Seems inefficient to do it with "" + i. Just simple Integer.toString or String.valueOf is recommended. See http://javadevnotes.com/java-integer-to-string-examples – JavaDev Feb 15 '15 at 14:18
15

Personally, I don't see anything bad in this code.

It's pretty useful when you want to log an int value, and the logger just accepts a string. I would say such a conversion is convenient when you need to call a method accepting a String, but you have an int value.

As for the choice between Integer.toString or String.valueOf, it's all a matter of taste.
...And internally, the String.valueOf calls the Integer.toString method by the way. :)

Franta
  • 986
  • 10
  • 17
ksu
  • 471
  • 4
  • 6
12

The other way I am aware of is from the Integer class:

Integer.toString(int n);
Integer.toString(int n, int radix);

A concrete example (though I wouldn't think you need any):

String five = Integer.toString(5); // returns "5"

It also works for other primitive types, for instance Double.toString.

See here for more details.

zneak
  • 134,922
  • 42
  • 253
  • 328
9

This technique was taught in an undergraduate level introduction-to-Java class I took over a decade ago. However, I should note that, IIRC, we hadn't yet gotten to the String and Integer class methods.

The technique is simple and quick to type. If all I'm doing is printing something, I'll use it (for example, System.out.println("" + i);. However, I think it's not the best way to do a conversion, as it takes a second of thought to realize what's going on when it's being used this way. Also, if performance is a concern, it seems slower (more below, as well as in other answers).

Personally, I prefer Integer.toString(), as it is obvious what's happening. String.valueOf() would be my second choice, as it seems to be confusing (witness the comments after darioo's answer).

Just for grins :) I wrote up classes to test the three techniques: "" + i, Integer.toString, and String.ValueOf. Each test just converted the ints from 1 to 10000 to Strings. I then ran each through the Linux time command five times. Integer.toString() was slightly faster than String.valueOf() once, they tied three times, and String.valueOf() was faster once; however, the difference was never more than a couple of milliseconds.

The "" + i technique was slower than both on every test except one, when it was 1 millisecond faster than Integer.toString() and 1 millisecond slower than String.valueOf() (obviously on the same test where String.valueOf() was faster than Integer.toString()). While it was usually only a couple milliseconds slower, there was one test where it was about 50 milliseconds slower. YMMV.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
GreenMatt
  • 18,244
  • 7
  • 53
  • 79
  • 1
    Don't forget to take the JIT into account - the first few conversions will be much slower and distort the timings. On my MacBook the concatenation takes ~20ns longer than the other two methods (which both take ~50ns per conversion), so the differences you saw in the order of ms are probably due to random error (scheduling, interrupts, etc). – SimonJ Nov 05 '10 at 18:24
7

There are three ways of converting to Strings

  1. String string = "" + i;
  2. String string = String.valueOf(i);
  3. String string = Integer.toString(i);
Suresh Maidaragi
  • 2,173
  • 18
  • 25
Vihaan Verma
  • 12,815
  • 19
  • 97
  • 126
6

It depends on how you want to use your String. This can help:

String total =  Integer.toString(123) + Double.toString(456.789);
Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90
6

There are various ways of converting to Strings:

StringBuilder string = string.append(i).toString();
String string = String.valueOf(i);
String string = Integer.toString(i);
Shailej Shimpi
  • 145
  • 2
  • 3
  • StringBuilder string = string.append(i).toString(); ... Hm, so is it the StringBuilder, or a String? Some mess here... – Franta Jan 13 '18 at 07:08
5
String strI = String.valueOf(i);

String string = Integer.toString(i);

Both of the ways are correct.

Paul Rooney
  • 20,879
  • 9
  • 40
  • 61
Shailej Shimpi
  • 145
  • 2
  • 3
5

Mostly ditto on SimonJ. I really dislike the ""+i idiom. If you say String.valueOf(i), Java converts the integer to a string and returns the result. If you say ""+i, Java creates a StringBuilder object, appends an empty string to it, converts the integer to a string, appends this to the StringBuilder, then converts the StringBuilder to a String. That's a lot of extra steps. I suppose if you do it once in a big program, it's no big deal. But if you're doing this all the time, you're making the computer do a bunch of extra work and creating all these extra objects that then have to be cleaned up. I don't want to get fanatic about micro-optimization, but I don't want to be pointlessly wasteful either.

Jay
  • 26,876
  • 10
  • 61
  • 112
5

There are many way to convert an integer to a string:

1)

Integer.toString(10);

2)

 String hundred = String.valueOf(100); // You can pass an int constant
 int ten = 10;
 String ten = String.valueOf(ten)

3)

String thousand = "" + 1000; // String concatenation

4)

String million = String.format("%d", 1000000)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hoque MD Zahidul
  • 10,560
  • 2
  • 37
  • 40
  • 1
    String.format("%d", 1000000) ... This is not really Int>>String conversion, this is rather String>>String processing here, despite overloaded. So I do not recommand this. Definitely not for purposes of just a conversion. – Franta Jan 13 '18 at 07:12
3

Using "" + i is the shortest and simplest way to convert a number to a string. It is not the most efficient, but it is the clearest IMHO and that is usually more important. The simpler the code, the less likely you are to make a mistake.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 2
    How would one make a mistake in calling String.valueOf or Integer.toString? – Eva Jul 23 '12 at 07:10
  • 1
    I have come across a couple of non-ideal uses of String.valueOf() but I can't remember them now. While the output was correct it was less efficient than `""+i` – Peter Lawrey Jul 23 '12 at 07:12
2

Personally I think that "" + i does look as the original question poster states "smelly". I have used a lot of OO languages besides Java. If that syntax was intended to be appropriate then Java would just interpret the i alone without needing the "" as desired to be converted to a string and do it since the destination type is unambiguous and only a single value would be being supplied on the right. The other seems like a 'trick" to fool the compiler, bad mojo when different versions of Javac made by other manufacturers or from other platforms are considered if the code ever needs to be ported. Heck for my money it should like many other OOL's just take a Typecast: (String) i. winks

Given my way of learning and for ease of understanding such a construct when reading others code quickly I vote for the Integer.toString(i) method. Forgetting a ns or two in how Java implements things in the background vs. String.valueOf(i) this method feels right to me and says exactly what is happening: I have and Integer and I wish it converted to a String.

A good point made a couple times is perhaps just using StringBuilder up front is a good answer to building Strings mixed of text and ints or other objects since thats what will be used in the background anyways right?

Just my two cents thrown into the already well paid kitty of the answers to the Mans question... smiles

EDIT TO MY OWN ANSWER AFTER SOME REFLECTION:

Ok, Ok, I was thinking on this some more and String.valueOf(i) is also perfectly good as well it says: I want a String that represents the value of an Integer. lol, English is by far more difficult to parse then Java! But, I leave the rest of my answer/comment... I was always taught to use the lowest level of a method/function chain if possible and still maintains readablity so if String.valueOf calls Integer.toString then Why use a whole orange if your just gonna peel it anyways, Hmmm?

To clarify my comment about StringBuilder, I build a lot of strings with combos of mostly literal text and int's and they wind up being long and ugly with calls to the above mentioned routines imbedded between the +'s, so seems to me if those become SB objects anyways and the append method has overloads it might be cleaner to just go ahead and use it... So I guess I am up to 5 cents on this one now, eh? lol...

David
  • 21
  • 2
2

As already pointed out Integer.toString() or String.valueOf() are the way to go. I was curious and did a quick benchmark:

Integer.toString(i) and String.valueOf(i) are basically identical in performance, with Integer.toString(i) being a tiny bit faster. However i + "" is 1.7 times slower.

import java.util.Random;

public class Test {

    public static void main(String[] args) {
        long concat = 0;
        long valueOf = 0;
        long toString = 0;
        
        int iterations = 10000;
        int runs = 1000;
        for(int i = 0; i < runs; i++) {
            concat += concat(iterations);
            valueOf += valueOf(iterations);
            toString += to_String(iterations);
        }
        
        System.out.println("concat: " + concat/runs);
        System.out.println("valueOf: " + valueOf/runs);
        System.out.println("toString: " + toString/runs);
    }
    
    public static long concat(int iterations) {
        Random r = new Random(0);
        long start = System.nanoTime();
        for(int i = 0; i < iterations; i++) {
            String s = r.nextInt() + "";
        }
        return System.nanoTime() - start;
    }
    
    public static long valueOf(int iterations) {
        Random r = new Random(0);
        long start = System.nanoTime();
        for(int i = 0; i < iterations; i++) {
            String s = String.valueOf(r.nextInt());
        }
        return System.nanoTime() - start;
    }
    
    public static long to_String(int iterations) {
        Random r = new Random(0);
        long start = System.nanoTime();
        for(int i = 0; i < iterations; i++) {
            String s = Integer.toString(r.nextInt());
        }
        return System.nanoTime() - start;
    }
}

Output:

concat: 1004109
valueOf: 590978
toString: 587236
das Keks
  • 3,723
  • 5
  • 35
  • 57
  • well you miss an important piece, in that String.valueOf and Integer.toString always create a new String object, while "" + int uses String pool. If you change your test from random to for example, always 1, the results are: concat: 759 valueOf: 107129 toString: 112058 – klarki May 23 '23 at 06:43
-2

use Integer.toString(tmpInt).trim();

Karan Chunara
  • 518
  • 4
  • 15
-6

Try simple typecasting

char c = (char) i;
ΦXocę 웃 Пepeúpa ツ
  • 47,427
  • 17
  • 69
  • 97
Bilal Haider
  • 83
  • 2
  • 6
  • 3
    This is not a good way to convert an int to a string. Actually, you are not converting an int to a string, you are converting an int to a char. This will interpret the int as an ASCII character code and give you that char. It's dangerous (negative values, etc.) and overall just plain wrong. – Nepoxx Dec 08 '14 at 19:35
  • Please clear the above question, char and String both are different...! –  Jun 18 '16 at 10:06
  • but this works (ASCII charset "offset"): `char c = (char) (i + 48);` – electrobabe Oct 05 '17 at 14:01