Java中的String对象是不可变的吗?

问题描述:

String s = ...; 

s = s.substring(1); 

这可能吗?我以为你不能在Java中改变一个String对象。Java中的String对象是不可变的吗?

+1

如果只有's.substring(1)'会改变's'中的字符串,那么你应该是正确的。但是你正在为's'分配一个新的字符串。 – 2010-08-03 15:38:20

+1

您只是更改引用s,而不是原始字符串本身。一个小样式点 - 创建一个新的,描述性命名的局部变量通常更好,而不是像这样重新使用变量。 – mikera 2010-08-03 15:41:00

+6

不要将对象与引用混淆。对象可能是可变的或不可变的。参考文献可能是“最后”或不是。制作引用'final'不会使对象不可变。不可变的对象可以通过引用来引用,而不必是“final”。 – polygenelubricants 2010-08-03 15:54:54

字符串对象是不可变的。然而,字符串引用是可变的。以上,s是一个参考。

+1

+1简短且正确。 s的初始值仍然存在,在内存中保持不变,可能现在未被引用 - 等待GC'd。但是,引用现在指向一个新的,同样不可变的对象,由substring方法创建。 – delnan 2010-08-03 15:39:15

+3

Dang,我希望在你看到这个Q之前,让自己成为一堆简单的代表。 :) +1 – iandisme 2010-08-03 15:41:42

在这里,您正在创建一个新的字符串并将其分配给一个预先使用的参考。被引用的原始字符串是垃圾收集。实际上没有字符串改变

+0

垃圾收集?? – 2013-07-30 09:29:31

字符串对象是不可变的,这意味着s引用的实例的值不能更改。

您的代码不会改变实例。
相反,它将s引用更改为引用新的字符串实例。

例如:

String a = "1"; 
String b = a; 
a = "2"; 

执行该代码后,b仍然"1"
b = a设置b指的是a当前所指的相同的"1"实例。
当您随后编写a = "2"时,您正在更改a变量以引用不同的("2")实例。
但是,原来的"1"实例,其中b仍然指向,没有改变。

是的,String对象是不可变的。

变量s是对对象的引用,引用本身可以让它指向的对象发生更改 - 重新分配引用不会影响它指向的对象。

String.substring方法实际上是返回一个String的新实例,因此原始的String对象保持不变。

下面是一个简单的例子来表明原来String没有被substring方法::

String s = "Hello!"; 
s.substring(1); 

System.out.println(s); // Prints "Hello!" 

上面的例子将改变打印“你好!”因为substring方法将返回一个新的String而不是影响原来的。原始String不可更改,因为它是不可变的。

比较上述具有以下:

String s = "Hello!"; 
s = s.substring(1); 

System.out.println(s); // Prints "ello!" 

在这个例子中,参考到s被改变为由substring方法返回的String,所以当与s相关联的String由`系统打印。 out.println“,输出的字符串将是”ello!“

所以:

String foo = "foo"; 
foo.substring(1); 
System.out.println(foo); 

//of course.. 
foo = "aa"; 
System.out.println(foo); 

当你用String s = ”ABC“,创建一个字符串引用具有不可变值的String对象 ”ABC“

然后,你的时候。比如s = s.substring(1);你将s赋值给新创建的包含“bc”的String对象 - 但原始对象不变赋值时,可能会得到意想不到的结果。

许多新手Java开发人员将使用像trim()这样的方法,但并未意识到trim()不会影响String。

s.trim()< - 什么也没有,返回一个修剪过的字符串 - 这是一个错误。

s = s.trim()< - 存储修剪过的字符串 - 这是正确的。

测试:

String s = "Test"; 
String j = s; 

s = s.substring(1); 

s现在Tj仍然Test

//创建参考s到字符串 “Hello”

的String = “你好”;串的

//现在打印SUBSTRING由s称为

的System.out.println(s.subString(1));

//现在打印字符串由s称为

的System.out.println(一个或多个);

上面代码段会第一打印ħ,然后在第二线它将打印你好现在为什么首先打印H? :事情是subString()方法返回一个字符串 * 而不更改引用s *引用的字符串。 s仍然指“你好”。现在,当您尝试打印s时,它会打印s所指向的字符串。以这种方式字符串“你好”是不可变的。你只是能够使用它来产生另一个字符串,但你不能改变它。

当使用语句s = s.subString(1); 你在做什么是s现在引用了“Hello”的subString(),但是“Hello”本身仍然没有被修改。