我应该如何在Java中复制字符串?

Séb*_*ien 180 java

    String s = "hello";
    String backup_of_s = s;
    s = "bye";
Run Code Online (Sandbox Code Playgroud)

此时,备份变量仍然包含原始值"hello"(这是因为String的不变性吗?).

但是使用这种方法复制字符串是否真的安全(复制常规可变对象当然不安全),或者写这个更好?:

    String s = "hello";
    String backup_of_s = new String(s);
    s = "bye";
Run Code Online (Sandbox Code Playgroud)

换句话说,这两个片段之间有什么区别(如果有的话)?


编辑 - 第一个片段安全的原因:

让我根据已经提供的好答案(主要关注两个片段之间的性能差异问题),更详细地解释一下事情:

字符串在Java中是不可变的,这意味着String对象在构造后不能被修改.因此,

String s = "hello";创建一个新的String实例并将其地址分配给s(s作为对实例/对象的引用)

String backup_of_s = s;创建一个新变量backup_of_s并初始化它,以便它引用当前引用的对象s.

注意:字符串不变性保证不会修改此对象:我们的备份是安全的

注2:Java垃圾收集机制保证只要至少有一个变量(backup_of_s在这种情况下)引用该对象,就不会销毁该对象

最后,s = "bye";创建另一个String实例(由于不变性,这是唯一的方法),并修改s变量,使其现在引用新对象.

NPE*_*NPE 127

由于字符串是不可变的,因此两个版本都是安全的 然而,后者效率较低(它创建了一个额外的对象,在某些情况下复制了字符数据).

考虑到这一点,首选版本应该是首选.

  • 不变性与它无关.它只是对象引用的工作方式.我可以提供一个等效的StringBuilder示例. (13认同)
  • @Sebastien所有它正在做的是重新分配引用变量`s`来引用另一个对象(`String`"bye").这不会影响引用变量`backup_of_s`引用的内容(`String`"hello").就像我说的那样,我可以提供一个与`StringBuilder'相同的例子,它不是不可变的.我的评论主要是关于OPs声明:_在这一点上,备份变量仍然包含原始值"hello"(这是因为String的不变性对吧?). (4认同)
  • @GriffeyDog:我正在逐字逐句地阅读这个问题.我所说的是,提供对字符串对象的引用是安全的,而不必担心有人可能会修改字符串. (3认同)
  • @BalusC,我看不出 new String() 如何在 JVM 的字符串池中创建任何内容。池中只有字符串文字和通过 intern() 提交到池中的文字。 (2认同)
  • @GriffeyDog我发现你的评论非常误导:不变性是第一个片段安全的原因,为什么你会说它与"它"无关? (2认同)

ale*_*oot 19

字符串是不可变对象,因此您可以复制它们只是处理它们的引用,因为引用的对象不能更改...

因此,您可以像第一个示例中一样进行复制,没有任何问题

String s = "hello";
String backup_of_s = s;
s = "bye";
Run Code Online (Sandbox Code Playgroud)


Dav*_*nan 10

您的第二个版本效率较低,因为它在没有必要时会创建一个额外的字符串对象.

不可变性意味着您的第一个版本的行为与您期望的一样,因此是首选的方法.