How is concatenation of final strings done in Java

2019-01-25 05:34发布

When I compile this snippet.

public class InternTest {
    public static void main(String...strings ){
        final String str1="str";
        final String str2="ing";
        String str= str1+str2;

    }
}

Which produces the following byte code

public static void main(java.lang.String...);
   flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
   Code:
     stack=1, locals=4, args_size=1
        0: ldc           #16                 // String str
        2: astore_1
        3: ldc           #18                 // String ing
        5: astore_2
        6: ldc           #20                 // String string
        8: astore_3
        9: return

so string literal "string" is already there in the constant pool which gets pushed 6: ldc #20 // String string on stack at this line.

Quoting JSL

From JLS §4.12.4 - final Variables:

A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable.

Also from JLS §15.28 - ConstantExpression:

Compile-time constant expressions of type String are always "interned" so as to share unique instances, using the method String#intern().

So i know str1 and str2 will be interned the moment it has been created."str" and "ing" will share the same memory at line String str= str1+str2; But how str1+str2 directly produces "string" in the constant string pool. Without invoking any String Builder class like it does when i don't write final. ? To see if it has got anything to do with intern things

I wrote this snippet

public class IntermTest {
    public static void main(String...strings ){
         String str1=("str").intern();
        String str2=("ing").intern();
        String str= str1+str2;

    }
}

But when i generated the byte code i got this

public static void main(java.lang.String...);
    flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
    Code:
      stack=3, locals=4, args_size=1
         0: ldc           #16                 // String str
         2: invokevirtual #18                 // Method java/lang/String.intern:
()Ljava/lang/String;
         5: astore_1
         6: ldc           #24                 // String ing
         8: invokevirtual #18                 // Method java/lang/String.intern:
()Ljava/lang/String;
        11: astore_2
        12: new           #26                 // class java/lang/StringBuilder
        15: dup
        16: aload_1
        17: invokestatic  #28                 // Method java/lang/String.valueOf
:(Ljava/lang/Object;)Ljava/lang/String;
        20: invokespecial #32                 // Method java/lang/StringBuilder.
"<init>":(Ljava/lang/String;)V
        23: aload_2
        24: invokevirtual #35                 // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
        27: invokevirtual #39                 // Method java/lang/StringBuilder.
toString:()Ljava/lang/String;
        30: astore_3
        31: return

Indeed it also uses stringBuilder for concatenation. So it has do something with final. Is there something special about final Strings that I'm definitely not aware of ?

1条回答
劳资没心,怎么记你
2楼-- · 2019-01-25 05:42

http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28 says that

Simple names (§6.5.6.1) that refer to constant variables (§4.12.4) are constant expressions.

http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28 also says:

A constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

  • Literals of primitive type and literals of type String (§3.10.1, §3.10.2, §3.10.3, §3.10.4, §3.10.5)
  • [...]
  • The additive operators + and - (§15.18)
  • [...]
  • Simple names (§6.5.6.1) that refer to constant variables (§4.12.4).

Example 15.28-1. Constant Expressions

[...]

"The integer " + Long.MAX_VALUE + " is mighty big."

Since those two variables are constant expressions, the compiler does the concatenation:

String str = str1 + str2;

is compiled the same way as

String str = "str" + "ing";

which is compiled the same way as

String str = "string";
查看更多
登录 后发表回答