Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When I do ""+1 I get a String - Why

Tags:

java

Please understand firstly that I fully understand that Java will return a String when I use ""+int.

What I'm really not sure about is what exactly is happening down at the memory aspect. How exactly is java performing this conversion. I mean this in a very indepth way, not 'auto boxing' or anything like that :)

I'm hoping someone with a deeper understanding can explain what exactly is done.

like image 304
Steve Avatar asked Mar 19 '10 16:03

Steve


4 Answers

Actually, for "" + 1 the compiler creates a String constant String with the value of "1" and puts it into the constant pool - so nothing is done at runtime.

If you have "" + x (where x is an int variable) you get the following bytecode (from the current JDK 1.6):

  0:   new     #2; //class java/lang/StringBuilder
  3:   dup
  4:   invokespecial   #3; //Method java/lang/StringBuilder."<init>":()V
  7:   ldc     #4; //String
  9:   invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
  12:  aload_0
  13:  arraylength
  14:  invokevirtual   #6; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
  17:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
  20:  astore_1
  21:  return

So it creates a StringBuilder, appends the "" to it, then appends the int value to it, then calls toString on the StringBuilder instance.

Inside the StringBuilder.append(int) method it ultimately calls Integer.getChars (a package private method).

You can look up the source to the append and getChars in the your copy of the JDK src.zip (or src.jar).

like image 57
TofuBeer Avatar answered Nov 03 '22 11:11

TofuBeer


The + is treated as a string concatenation because a String is on one side of the operand - this would work on 1+"" as well. Thus 1 is implicitly converted into the string "1" and "" concatenated with it, resulting in ""+"1" => "1".

This is sometimes used as a quick and dirty way to convert an integer variable to String, e.g.

String s = "" + myInt;

But the "proper" way to do this would be:

String s = Integer.toString(myInt);

or alternatively:

String s = String.valueOf(myInt);

Edit:

To clarify, the compiler makes this determination and inserts code that will cast the integer into a string before the concatenation is performed.

So basically the compiler sees:

String s = "" + myInt;

And effectively creates bytecode equivalent of

String s = "" + String.valueOf(myInt)

Although it will probably in practice optimize the concatenation away.

like image 31
Kris Avatar answered Nov 03 '22 10:11

Kris


Java Language Specification 15.18.1.1 String Conversion

Any type may be converted to type String by string conversion.

A value x of primitive type T is first converted to a reference value as if by giving it as an argument to an appropriate class instance creation expression:

  • If T is boolean, then use new Boolean(x).
  • If T is char, then use new Character(x).
  • If T is byte, short, or int, then use new Integer(x).
  • If T is long, then use new Long(x).
  • If T is float, then use new Float(x).
  • If T is double, then use new Double(x).

This reference value is then converted to type String by string conversion.

Now only reference values need to be considered. If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l). Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.

The toString method is defined by the primordial class Object; many classes override it, notably Boolean, Character, Integer, Long, Float, Double, and String.

like image 33
axtavt Avatar answered Nov 03 '22 10:11

axtavt


Some of these quotes are edited for relevance, and emphasis may be added.

JLS 15.18.1 String Concatenation Operator +

If only one operand expression is of type String, then string conversion is performed on the other operand to produce a string at run time. The result is a reference to a String object that is the concatenation of the two operand strings.

JLS 15.18.1.1 String Conversion

  • A value x of primitive type T is first converted to a reference value as if by giving it as an argument to an appropriate class instance creation expression:
    • If T is byte, short, or int, then use new Integer(x).
  • Now only reference values need to be considered. The conversion is performed as if by an invocation of the toString() method.

According to this specification, "" + i is evaluated as if it was written as "" + new Integer(i).toString(). The operation is string concatenation, which results in a string.

Do note the phrase "as if" in the above passages; only correct behavior is precisely specified, but how that is accomplished under the hood is left to the implementation.

A few things that I omitted from this discussion for now are:

  • null is always converted to "null"
  • Inlining of compile-time constants (JLS 15.28)
  • Optimization using the mutable StringBuffer/StringBuilder (JLS 15.18.1.2)
like image 33
polygenelubricants Avatar answered Nov 03 '22 11:11

polygenelubricants