【问题标题】:Does `+=` operator always create a new string object?`+=` 运算符是否总是创建一个新的字符串对象?
【发布时间】:2018-04-27 18:20:56
【问题描述】:

如果池内存已经有一个内容相似的对象,那么如果我们尝试用不同的引用变量创建同一个对象,那么只会创建一个新的引用变量,没有新的对象被创建。例如;

String s7="1";
String s8 ="1";
System.out.print(s7==s8);  //True

这里只创建了一个对象。 但在下面的例子中

public class JavaApplication1 {
    public static void main(String[] args) {
        String s1 = "1", s2 = "2", s4 = s1 + s2, s5 = "12";
        final String s3 = s1 + s2;
        s1 += s2;
        System.out.print((s1 == s3) + "" + (s1 == s5) + "" + "" (s3 == s5));
    }
}

输出为假假假 Even is s3 被声明为最终表达式!,为什么?

【问题讨论】:

  • 因为s1 和s2 不是吗?这与“增量”有什么关系?
  • += 就像在 s1+=s2;
  • AFAIK,编译器只实习明显的情况 - 直接字符串常量及其连接。在运行时处理其他任何内容。
  • @Krishnan no:编译时常量是最终的,但最终值并不总是编译时常量。考虑final String s = "" + System.currentTimeMillis();:无法在编译时进行评估。

标签: java string memory


【解决方案1】:

这是因为

1) 由常量表达式(第 15.28 节)计算的字符串在编译时计算,然后将其视为文字。

2) 在运行时通过连接计算的字符串是新创建的,因此是不同的。

这是一个例子:

    String s7 = "77";
    String s8 = "77";

    String s10 = "7";
    String s11 = "7";

    String s9 = s10+s11;
    String s12 = "7"+"7";

    //printing the address
    System.out.println(System.identityHashCode(s7));
    System.out.println(System.identityHashCode(s8));
    System.out.println(System.identityHashCode(s9));
    System.out.println(System.identityHashCode(s12));

    System.out.println(s7==s9);
    System.out.println(s7==s12);

输出:

705927765
705927765
366712642  ---> address is different
705927765
false
true

虽然我刚才也经历过这件事。但这是我的假设:

除了String s9 = s10+s11; 之外的所有文字都是在编译时计算的。这就是我们得到不同地址的原因。

关注String literals javadoc了解更多详情。

【讨论】:

    【解决方案2】:

    If pool memory already has an object with similar content, then if we try to create the same object with different reference variable then only a new reference variable is created, NO NEW OBJECT IS CREATED.eg;

    在一般情况下实际上并非如此。您所描述的内容称为String interning。 interned 字符串将始终与任何其他具有相同内容的实习字符串相同——这基本上是intern 的保证。 (来自String.intern 上的docs:因此对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为是的。)。如果我要从一个常量字节数组创建 2 个字符串,那么即使它们共享内容,它们也将是不同的对象。

    JLS 进一步说明:
    此外,字符串字面量始终指代 String 类的同一个实例。这是因为字符串字面量 - 或者更一般地说,作为常量表达式值的字符串(第 15.28 节) - 是“内部的”,以便使用 String.intern 方法共享唯一实例。

    这就是为什么你会得到字符串文字的相等性,以及任何 [a] 常量表达式的 值。

    那么,这个常量表达式是什么?好吧,再一次,根据 JLS,这些是文字,引用常量变量的简单名称(第 6.5.6.1 节),各种非字符串内容,以及带有 + 的表达式,但仅作为只要+ 的两个操作数本身都是constant expressions(String 对象是新创建的(§12.5),除非表达式是常量表达式(§15.28)。)。所以这意味着,除非您在+ 的 both 两侧的字符串是文字,否则最终字符串的值为 constant 表达式 或满足其他条件之一(例如原始常量的强制转换),将创建一个新对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-11-05
      • 2012-01-02
      • 1970-01-01
      • 1970-01-01
      • 2019-09-20
      • 1970-01-01
      • 2012-08-12
      • 1970-01-01
      相关资源
      最近更新 更多