Java 中如何连接最终字符串?
How is concatenation of final strings done in Java?
当我编译这段代码时。
public class InternTest {
public static void main(String...strings ){
final String str1="str";
final String str2="ing";
String str= str1+str2;
}
}
产生以下字节码
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
所以字符串文字 "string" 已经存在于常量池中,并被推送 6: ldc #20 // String string
到栈中这一行。
引用 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().
所以我知道 str1 和 str2 将在创建时被保留。"str" 和 "ing" 将在第 String str= str1+str2;
行共享相同的内存
但是str1+str2如何在常量字符串池中直接产生"string"。没有像我不写 final
. 时那样调用任何 String Builder class ?看看是不是跟实习生的事情有关系
我写了这个片段
public class IntermTest {
public static void main(String...strings ){
String str1=("str").intern();
String str2=("ing").intern();
String str= str1+str2;
}
}
但是当我生成字节码时,我得到了这个
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
实际上它也使用 stringBuilder
进行连接。所以它对final做了一些事情。 final
字符串有什么我绝对不知道的特别之处吗?
http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28 表示
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 还说:
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."
由于这两个变量是常量表达式,编译器会进行连接:
String str = str1 + str2;
的编译方式与
相同
String str = "str" + "ing";
编译方式与
相同
String str = "string";
当我编译这段代码时。
public class InternTest {
public static void main(String...strings ){
final String str1="str";
final String str2="ing";
String str= str1+str2;
}
}
产生以下字节码
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
所以字符串文字 "string" 已经存在于常量池中,并被推送 6: ldc #20 // String string
到栈中这一行。
引用 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().
所以我知道 str1 和 str2 将在创建时被保留。"str" 和 "ing" 将在第 String str= str1+str2;
行共享相同的内存
但是str1+str2如何在常量字符串池中直接产生"string"。没有像我不写 final
. 时那样调用任何 String Builder class ?看看是不是跟实习生的事情有关系
我写了这个片段
public class IntermTest {
public static void main(String...strings ){
String str1=("str").intern();
String str2=("ing").intern();
String str= str1+str2;
}
}
但是当我生成字节码时,我得到了这个
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
实际上它也使用 stringBuilder
进行连接。所以它对final做了一些事情。 final
字符串有什么我绝对不知道的特别之处吗?
http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28 表示
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 还说:
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."
由于这两个变量是常量表达式,编译器会进行连接:
String str = str1 + str2;
的编译方式与
相同String str = "str" + "ing";
编译方式与
相同String str = "string";