Runtime String concatenation evaluation

According to JLS(15.28 Constant Expressions) An expression containing only:

i)Literals of primitive type and literals of type String (§3.10.1, §3.10.2, §3.10.3,
§3.10.4, §3.10.5)
or
ii)Simple names (§6.5.6.1) that refer to constant variables (§4.12.4).
or
iii)...

is a constant expression.

Now String s1="a"+"b"; is a constant expression and will be evaluated to "ab" at compile time.

so s1="ab";

[1] Am i right in saying that now there are three objects in String pool as according to above statement:-"a","b","ab"???

Now,

final String s="a";
final String s1="b";
String s2=s+s1;  // is also constant expression and get evaluated at compile time.

the above code will be transaled to s2="a"+"b"; after compilation.

so s2="ab"; will be stored in string pool automatically.

But,

// note there is no final now.
String s="a";
String s1="b";
String s2="a"+"b";  // constant expression.
String s3=s+s1;  // is NOT a constant expression and get evaluated at RUN TIME.

for String s3=s+s1; ,the code will be translated to :

s3=new StringBuilder(String.valueOf(s)).append(s1).toString();

and will create a new String object.

therefore, s2==s3 will comes out to be false;

Does that mean result of String concatenation evaluated at runtime using StringBuilder not get stored in String Pool but instead goes into heap(outside pool)?


From JLS §15.18.1:

15.18.1. String Concatenation Operator +

If only one operand expression is of type String, then string conversion (§5.1.11) is performed on the other operand to produce a string at run-time.

The result of string concatenation is a reference to a String object that is the concatenation of the two operand strings. The characters of the left-hand operand precede the characters of the right-hand operand in the newly created string.

The String object is newly created (§12.5) unless the expression is a compile-time constant expression (§15.28).

An implementation may choose to perform conversion and concatenation in one step to avoid creating and then discarding an intermediate String object. To increase the performance of repeated string concatenation, a Java compiler may use the StringBuffer class or a similar technique to reduce the number of intermediate String objects that are created by evaluation of an expression.

For primitive types, an implementation may also optimize away the creation of a wrapper object by converting directly from a primitive type to a string.

So,

  • There is one object in the constant pool ("ab"). The temporaries are not saved.
  • Likewise, there will only be "ab" in the constant pool.
  • The new string is a new String object and will not be in the pool unless explicitly interned.
  • It is instructive to look at some bytecode:

    String sa1 = "a"+ "b";
    
    final String sb1 = "a";
    final String sb2 = "b";
    String sb3 = sb1 + sb2;
    
    String sc1 = "a";
    String sc2 = "b";
    String sc3 = "a" + "b";
    String sc4 = sc1 + sc2;
    

    becomes

      Code:
       0:   ldc #2; //String ab
       2:   astore_0
       3:   ldc #2; //String ab
       5:   astore_3
       6:   ldc #3; //String a
       8:   astore  4
       10:  ldc #4; //String b
       12:  astore  5
       14:  ldc #2; //String ab
       16:  astore  6
       18:  new #5; //class java/lang/StringBuilder
       21:  dup
       22:  invokespecial   #6; //Method java/lang/StringBuilder."<init>":()V
       25:  aload   4
       27:  invokevirtual   #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       30:  aload   5
       32:  invokevirtual   #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
       35:  invokevirtual   #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
       38:  astore  7
       40:  return
    

    You can see that in the first two cases, "ab" is loaded straight from the constant pool. In the third block, we get the translation sc4 = new StringBuilder().append(sc1).append(sc2).toString() , which creates a new object.


    Am i right in saying that now there are three objects in String pool as according to above statement:-"a","b","ab"???

    No. You are incorrect. The concatenation is performed at compile time, and only the "ab" object will be stored in the string pool.

    Does that mean result of String concatenation evaluated at runtime using StringBuilder not get stored in String Pool but instead goes into heap(outside pool)?

    Yes, you are correct on this point.


    In summary, string literals and the values of compile-time constant string expressions will be interned (and stored in the string pool). The results of other string concatenations will not be interned ... unless you explicitly call String.intern() . (And you should rarely do that ... because interning strings usually does more harm than good.)

    Either way, you should avoid using == to compare strings.


    Does that mean result of String concatenation evaluated at runtime using StringBuilder not get stored in String Pool but instead goes into heap(outside pool)

    Yes. That is correct. It will create new object in heap.

    链接地址: http://www.djcxy.com/p/64700.html

    上一篇: Modernizr CSS规则被Safari忽略(Mobile Safari也是如此)

    下一篇: 运行时字符串连接评估