简体   繁体   中英

When I do “”+1 I get a String - Why

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.

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).

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, eg

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.

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.

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 )

“a”+“b”只是StringBuilder.append(“a).append(”b“)的语法糖,因为你可以.append(1)并自动将它转换为你所看到的String 。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM