【问题标题】:Why concatenating two Strings and passing it as argument does not create a new String Object?为什么连接两个字符串并将其作为参数传递不会创建新的字符串对象?
【发布时间】:2014-01-10 15:39:49
【问题描述】:

我正在学习并准备参加 Java SE 6 认证。我正在使用 Kathy Sierra 和 Bert Bates 的书“Sun Certified Programmer for Java 6 Study Guide”。我实际上是在字符串、I/O 和解析方面。

他们提供了一个我可能期望在考试中看到的那种恶魔般的字符串问题的例子:

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

输出是什么?对于额外的功劳,有多少 String 对象以及如何 在 println 语句之前创建了许多引用变量?

答案:这段代码片段的结果是spring winter spring 夏天。有两个参考变量,s1 和 s2。有一个 总共创建了八个 String 对象,如下所示:“spring”、“summer” (迷路)、“春夏”、“秋天”(迷路)、“春秋”(迷路)、“春天” 夏春”(丢失)、“冬”(丢失)、“春冬”(此时 “弹簧”丢失)。八个 String 对象中只有两个没有丢失 在这个过程中。

我在标题中的问题非常具体。如您所见,他们说总共有 8 个String 对象,但是,在 println 方法调用时会发生什么?它传递一个 String 对象引用作为参数,因此 s1 加上 s2 的值应该创建另一个 String 对象,因为它是不可变的,将计数增加到 9。

但是(可能更多)不应该在 s1 和 s2 的值之间的空字符串 (" ") 创建其他对象,将计数增加到 10 吗?

他们这样做的时候很重要:

s1.concat("下降");

那么,为什么不这样:

s1.concat(s1 + " " + s2);

或真正的,这个:

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

【问题讨论】:

  • 我猜“在 println 语句之前”是指在整行之前,而不是在输入 println 方法之前。
  • 请记住,编译器也会优化字符串(如果可以的话)。如果你有 String s1 = "spring" + " " + "summer",编译器会将它变成一个。不确定编译器是否足够聪明以优化第 2 行 - 因为您使用的是变量而不是“spring”。
  • 其实,“spring”、“summer”、“fall”和“winter”并不是在上面创造出来的——它们是从原始的软泥中产生的。
  • 当然,这两个 concat 操作在创建字符串时完全是噪音——它们没有任何效果。

标签: java string scjp


【解决方案1】:

因为带有操作词prior的语句:'

prior to the println statement

8 String 对象是在您描述的 println 之前(之前)创建的。另外 2 个是在 println" "spring winter spring summer 上创建的

String s1 = "spring ";             // "spring" created, reference s1 changed
String s2 = s1 + "summer ";        // "summer", "spring summer" created, "summer" not saved, reference s2 changed
s1.concat("fall ");                // "fall", "spring fall" created but not saved
s2.concat(s1);                     // "spring summer spring" created but not saved
s1 += "winter ";                   // "winter", "spring winter" created, reference s1 changed
System.out.println(s1 + " " + s2); //" ", "spring winter spring summer" created, " "  not saved

注意:“已创建”并不意味着在代码中此时已创建,只是这段代码会要求创建它。

【讨论】:

  • 请注意,“spring”不是由上述语句创建的。它至少在类加载后就存在了,如果不是之前的话。
  • 哇,现在我看到了“之前”这个词。我想我必须仔细阅读,特别是如果我要参加那次考试。所以,我是对的。有 10 个对象。在执行该行之前,我不知道那些字符串在堆中!谢谢
  • 一个问题:如果我有:“Boolean b = true; Integer i = 10; etc.”,这些对象是在那时创建的,或者正如你们两个所说的那样,字符串文字会发生这种情况?
  • @GabrielBB - 编写一个测试用例并使用javap 转储字节码以找出答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多