创建了多少个String对象
我正在为SCJP学习我似乎无法理解这个String问题。我似乎看到几个可能的答案取决于我如何看待问题。
在以下初始化中,创建了多少个字符串对象?
String s1 = "A" + "B" + "C" + "D";
System.out.println(s1)
最初我想到了5个对象,即
"A"
"B"
"C"
"D"
"ABCD"
但是后来考虑一下我不太确定,因为例如编译器会将"A" + "B"
连接成一个对象吗?即创造7个物体?
"A"
"B"
"C"
"D"
"AB"
"ABC"
"ABCD"
此外,如果代码更改为
,将创建多少个对象String s1 = new String("A" + "B" + "C" + "D");
System.out.println(s1);
最后怎么样:
String s1 = "A";
String s2 = new String("A");
在上面的例子中,我认为只会创建2个对象
object 1 - "A"
object 2 - a String object that refers to the "A" object above.
这是正确的还是不相关?即,从常量池引用的对象将不同于s2引用所引用的对象。
由于
此外,请注意我有兴趣了解创建的对象总数,包括那些最终丢弃的对象,而不仅仅是最终在常量池中的对象。
看看Jon的回答,我可能完全误解了对象的创建方式。我知道String只在常量池中创建一次并且它被重用但是我不确定在构造'final'字符串时经历的过程。以下是我正在阅读的书中的部分,它似乎表明临时对象的创建与此处的答案完全相反。 (或者这本书可能是错的,或者我误解了这本书)
代码示例
String s1 = "spring ";
String s2 = s1 + "summer ";
s1.concat("fall ");
s2.concat(s1);
s1 += "winter";
System.out.println(s1 + " " + s2);
问题是
输出是什么?对于额外的功劳,有多少String对象以及如何使用 在println语句之前创建了许多参考变量。
答案
此代码片段的结果为
spring water spring summer
。那里 是两个参考变量,s1和s2。共有八个 字符串对象创建如下“spring”,“summer”(丢失),“spring 夏天“,”跌倒“(迷失),”春天秋天“(迷失),”春夏“ (失去),“冬天”(迷失),“春天的冬天”(此时“春天”是 丢失)。八个String对象中只有两个不会丢失 过程
由于
答案 0 :(得分:13)
编译器会将整个“A”+“B”+“C”+“D”连接成一个常量 - 所以在你的第一个例子中,只有一个字符串最终会被创建 。如果多次执行相同的代码,将重用相同的字符串。常量放在类文件中,当加载类时,VM检查字符串池中是否已存在相等的字符串 - 因此即使在多个类中具有相同的代码,它也将重用它。
您可以使用javap
验证类中的常量池中只有一个字符串:
javap -v Test
Constant pool:
#1 = Methodref #6.#17 // java/lang/Object."<init>":()V
#2 = String #18 // ABCD
#3 = Fieldref #19.#20 // java/lang/System.out:Ljava/io/PrintStream;
但是,这里:
String s1 = "A";
String s2 = new String("A");
你最终会得到两个独立的字符串对象。每次执行代码时都会重复使用一个(常量)(并在两个语句之间共享),并且每次都会因为构造函数调用而创建一个 new 。
例如,这个方法:
public static void foo() {
for (int i = 0; i < 5; i++) {
String s1 = "A";
String s2 = new String("A");
}
}
...将使用六个字符串对象结束 - 一个用于常量,每次调用方法时创建五个 new 。
答案 1 :(得分:4)
创建了多少个对象?
String s1 = "A" + "B" + "C" + "D";
System.out.println(s1)
一个或没有。这减少到一个可以加载的字符串文字。
String s1 = new String("A" + "B" + "C" + "D");
System.out.println(s1);
这总会创建一个额外的对象。
BTW:字符串通常由两个对象组成,String
和char[]
包装。
答案 2 :(得分:2)
String s1 = "A" + "B" + "C" + "D";
编译器将只创建一个字符串文字“ABCD”并将其放入String池中。将创建一个对象(字符串池中的对象)。
String s1 = new String("A" + "B" + "C" + "D");
此处相同,只是您要从字符串文字中复制它。所以,这里将创建2个对象。一个由new
和一个在字符串池中。
String s1 = "A";
String s2 = new String("A");
同样,"A"
将是字符串池中的常量。构造函数将复制它。所以这里将创建两个对象。