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


197
    String s = "hello";
    String backup_of_s = s;
    s = "bye";

此时,备份变量仍包含原始值“ hello”(这是因为String的不可变性对吗?)。

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

    String s = "hello";
    String backup_of_s = new String(s);
    s = "bye";

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


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

让我基于已经提供的良好答案(主要集中在两个代码片段之间的性能差异问题)来更详细地说明事情:

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

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

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

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

注意2:Java垃圾回收机制保证只要该对象被至少一个变量引用(backup_of_s在这种情况下),它就不会被破坏。

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

Answers:


138

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

考虑到这一点,应该首选第一个版本。


14
不变性与它无关。这只是对象引用的工作方式。我可以提供一个等效的StringBuilder示例。
GriffeyDog 2012年

1
@BalusC,我看不到新的String()如何在JVM的字符串池中创建任何内容。池中仅包含字符串垃圾和那些通过intern()提交给池的垃圾。
尼克斯(Snicolas)2012年

3
@GriffeyDog:我不是从字面上读这个问题。我的意思是,给出对字符串对象的引用是安全的,而不必担心有人会修改该字符串。
NPE 2012年

2
@GriffeyDog我发现您的评论很有误导性:不变性是第一个摘要安全的原因,为什么您说它与“它”无关?
塞巴斯蒂安2014年

4
@Sebastien它所做的就是重新分配引用变量s以引用另一个对象(String“再见”)。这不会影响引用变量backup_of_s所指的内容(String“ hello”)。就像我说的,我可以提供一个与StringBuilders 相等的例子,它不是不变的。我的评论主要是关于OPs语句的:在这一点上,备份变量仍然包含原始值“ hello”(这是因为String的不变性正确吗?)。
GriffeyDog 2014年

22

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

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

String s = "hello";
String backup_of_s = s;
s = "bye";

10

您的第二个版本效率较低,因为它根本不需要创建额外的字符串对象。

不变性意味着您的第一个版本按照您的预期方式运行,因此是首选方法。



-16
String str1="this is a string";
String str2=str1.clone();

这样复制怎么样?我认为获得一个新副本会更好,以便在以后的操作中引用和修改str1时不会影响的数据str2


3
String是一成不变的。克隆字符串没有多大意义。
弗拉基米尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.