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

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

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

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

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


EDIT -第一个代码片段是安全的原因:

让我更详细地解释一下,基于已经提供的良好答案(基本上集中在两个片段之间的性能差异问题上):

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

字符串s = "hello";创建一个新的String实例并将其地址赋给s (s是对实例/对象的引用)

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

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

注2:Java垃圾收集机制保证只要该对象被至少一个变量(在本例中为backup_of_s)引用,它就不会被销毁。

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


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

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


第二个版本效率较低,因为它在根本不需要这样做的情况下创建了一个额外的字符串对象。

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


字符串是不可变的对象,所以你可以复制它们,只是复制它们的引用,因为引用的对象不能改变…

所以你可以像第一个例子一样复制,没有任何问题:

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

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

像这样复印一下怎么样? 我认为获取一个新的副本更好,这样在下一步操作中引用str2并修改str2时不会影响str1的数据。


第二种情况在String池方面也是低效的,您必须在返回引用时显式调用intern()以使其成为intern。