文字字符串创建与String对象创建

zig*_*ggy 7 java string scjp

创建了多少个String对象

我正在为SCJP学习,我似乎无法理解这个String问题.我似乎看到几个可能的答案取决于我如何看待问题.

在以下初始化中,创建了多少个字符串对象?

String s1 = "A" + "B" + "C" + "D";
System.out.println(s1)
Run Code Online (Sandbox Code Playgroud)

最初我认为5个对象,即

"A"
"B"
"C"
"D"
"ABCD"
Run Code Online (Sandbox Code Playgroud)

但是后来考虑一下我不太确定,因为例如编译器会连接"A" + "B"成一个对象吗?即创建7个对象?

"A"
"B"
"C"
"D"
"AB"
"ABC"
"ABCD" 
Run Code Online (Sandbox Code Playgroud)

此外,如果代码更改为,将创建多少个对象

String s1 = new String("A" + "B" + "C" + "D");
System.out.println(s1);
Run Code Online (Sandbox Code Playgroud)

最后怎么样:

String s1 = "A";
String s2 = new String("A");
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我认为只会创建2个对象

object 1 - "A"
object 2 - a String object that refers to the "A" object above.
Run Code Online (Sandbox Code Playgroud)

这是正确的还是不相关?即,从常量池引用的对象将不同于s2引用所引用的对象.

谢谢

编辑

此外,请注意我有兴趣知道创建的对象总数,包括那些被丢弃的对象,而不仅仅是那些最终在常量池中结束的对象.

编辑

看看Jon的回答,我可能完全误解了对象的创建方式.我知道String只在常量池中创建一次并且它被重用但是我不确定在构造'final'字符串时经历的过程.以下是我正在阅读的书中的部分,它似乎表明临时对象的创建与此处的答案完全相反.(或者这本书错了或我误解了这本书)

代码示例是

String s1 = "spring ";  
String s2 = s1 + "summer ";  
s1.concat("fall ");  
s2.concat(s1);  
s1 += "winter";  
System.out.println(s1 + " " + s2);
Run Code Online (Sandbox Code Playgroud)

问题是

什么是输出?为了额外的功劳,在println语句之前创建了多少个String对象和多少个引用变量.

答案

这段代码片段的结果是spring water spring summer.有两个参考变量,s1和s2.共有八个String对象创建如下"spring","summer"(丢失),"spring summer","fall"(丢失),"spring fall"(丢失),"spring spring spring"(丢失) ,"冬天"(迷失),"春天的冬天"(此时"春天"丢失了).在此过程中,八个String对象中只有两个不会丢失

谢谢

Jon*_*eet 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;
Run Code Online (Sandbox Code Playgroud)

但是,这里:

String s1 = "A";
String s2 = new String("A");
Run Code Online (Sandbox Code Playgroud)

你最终会得到两个独立的字符串对象.每次执行代码时都会重用一个(常量)(并在两个语句之间共享),并且每次都会由于构造函数调用而创建一个新的.

例如,这个方法:

public static void foo() {
    for (int i = 0; i < 5; i++) {
        String s1 = "A";
        String s2 = new String("A");
    }
}
Run Code Online (Sandbox Code Playgroud)

...将最终使用六个字符串对象 - 一个用于常量,每次调用方法时创建五个对象.

  • @MartijnCourteaux OOP的概念与它有什么关系? (2认同)