6

我被问到这个问题:

String s = "abc"; // creates one String object and one
          // reference variable
In this simple case, "abc" will go in the pool and s will refer to it.
String s = new String("abc"); // creates two objects,
                 // and one reference variable*

根据以上细节,在下面代码的 println 语句之前创建了多少个 String 对象和多少个引用变量?

String s1 = "spring ";
String s2 = s1 + "summer ";
s1.concat("fall ");
s2.concat(s1);
s1 += "winter ";
System.out.println(s1 + " " + s2);

我的回答是这段代码片段的结果是春冬春夏

有两个参考变量,s1 和 s2。一共创建了八个String对象,分别为:“spring”、“summer”(丢失)、“spring summer”、“fall”(丢失)、“spring fall”(丢失)、“spring summer spring”(丢失) )、“winter”(丢失)、“spring winter”(此时“spring”丢失)。

在这个过程中,八个 String 对象中只有两个没有丢失。

这是对的吗?

4

4 回答 4

4

答案是:2 个引用和 8 个对象。

String s1 = "spring "; //One reference and 1 object in string pool. (if it didn't exist already)

String s2 = s1 + "summer "; //Two references and 3 objects

s1.concat("fall "); //Two references and 5 objects

s2.concat(s1); //Two references and 6 objects

s1 += "winter "; //Two references and 8 objects

System.out.println(s1 + " " + s2);

现在你的问题是:Java 如何处理内存中的 String 对象?

Java 提供了两种创建类对象的方法String

  1. 字符串 str1 = "OneString";

在这种情况下,JVM 会搜索字符串池以查看是否已经存在等效字符串。如果是,则返回对相同的引用。如果没有,则将其添加到字符串池并返回引用。所以可能会创建一个新对象,也可能不会。

  1. 字符串 str1 = new String("OneString");

现在,JVM 必须在堆上创建一个对象。由于OneString字符串池中是否已经存在并不重要。

您还可以将字符串放入池中:

您可以在 String 对象上调用 intern()。如果 String 对象不存在,这会将其放入池中,并返回对池化字符串的引用。(如果它已经在池中,它只返回对已经存在的对象的引用)。

您可能想查看以下链接:

什么是 Java 字符串池,“s”与 new String(“s”) 有何不同?

关于Java的字符串池的问题

于 2012-01-25T07:25:22.190 回答
1

看起来正确。顺便说一句,这是一个 SCJP 考试问题。

concat 返回一个新的字符串,这是丢失的。第一个 s1 被“春冬”覆盖

关于 Java 中的字符串,你应该知道两件事:

  • 字符串是不可变的(您已经解释过)
  • 字符串可能驻留在字符串池中。并非每次您编写“Summer”时都会构造一个全新的字符串,不可变的“Summer”可能会从池中出来(取决于 JVM,但对于 Oracle,它是)。另见:http ://docs.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#intern ()

干杯基督徒

于 2012-01-25T06:42:55.430 回答
1

java中的字符串是不可变的。有分配的字符数组,以及一些周边信息,如偏移量和长度。如果您使用字符串文字来初始化字符串,编译器会尝试优化并为每个文字只创建一个字符串对象 - 这是可能的,因为它们是不可变的。

如果您对字符串进行连接或 +,则将分配新字符串并将数据编译在一起(性能损失。

与此相反,从字符串创建子字符串实际上是免费的 - 不会复制任何数据

于 2012-01-25T06:44:18.503 回答
1
String s = "abc"; // creates one String object and one 
                 // reference variable 

仅当对象不存在于字符串常量池中时才创建一个字符串对象。

String s = new String("abc"); // creates two objects,
                              // and one reference variable*  

这实际上只在堆中创建了一个对象。当且仅当在此 String 对象上调用 intern() 方法时,它才会将此对象添加到池中。

String s1 = "spring "; 
String s2 = s1 + "summer ";        
s1.concat("fall ");        
s2.concat(s1);        
s1 += "winter ";
System.out.println(s1 + " " + s2);   

您的解释似乎没问题,除了 System.out.println().:-)
当您说(丢失)时,它实际上意味着它不再是活动对象(堆栈上不存在引用)。

于 2012-01-25T07:26:48.450 回答