将为以下代码创建多少个对象?
String temp = "a" + "b" + "c"
我的理解:a,b和c是字符串文字,将存储在字符串池中(因此不会创建新对象)。然后在使用“+”运算符追加时,它在内部使用StringBuffer,因此将创建一个将保存“abc”(StringBuffer)的对象。它将在一个新的String对象中返回(其值为“abc”)。
- >因此,在此操作期间将创建总共2个对象。(一个String和一个StringBuffer)。
- >字符串池中也不会出现字符串“abc”。
我错了吗?
答案 0 :(得分:4)
从这个测试代码:
public class Test {
public static void main(final String[] args) {
String temp = "a" + "b" + "c";
}
}
你得到这个字节码:
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String abc
2: astore_1
3: return
使用此常量池:
Constant pool:
#1 = Methodref #4.#13 // java/lang/Object."<init>":()V
#2 = String #14 // abc
#3 = Class #15 // Test
#4 = Class #16 // java/lang/Object
#5 = Utf8 <init>
#6 = Utf8 ()V
#7 = Utf8 Code
#8 = Utf8 LineNumberTable
#9 = Utf8 main
#10 = Utf8 ([Ljava/lang/String;)V
#11 = Utf8 SourceFile
#12 = Utf8 Test.java
#13 = NameAndType #5:#6 // "<init>":()V
#14 = Utf8 abc
#15 = Utf8 Test
#16 = Utf8 java/lang/Object
所以你错了。创建了一个String
- "abc"
- 并在运行时放入String
池。
这里的编译器执行常量折叠并将编译时常量表达式"a" + "b" + "c"
简化为"abc"
。如果使用-XD-printflat
标志进行编译,可以看到这一点,该标志显示编译器编译为字节码的实际源:
public static void main(final String[] args) {
String temp = "abc";
}
如果要查看实际的String
连接,则必须使用非编译时常量的操作数,例如变量:
public static void main(final String[] args) {
String a = "a";
String b = "b";
String c = "c";
String temp = a + b + c;
}
获取编译为:
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String a
2: astore_1
3: ldc #3 // String b
5: astore_2
6: ldc #4 // String c
8: astore_3
9: new #5 // class java/lang/StringBuilder
12: dup
13: invokespecial #6 // Method java/lang/StringBuilder."<init>":()V
16: aload_1
17: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
20: aload_2
21: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
24: aload_3
25: invokevirtual #7 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
28: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
31: astore 4
33: return