2013-05-08 70 views
12

我想了解Java字符串是如何不可变的。我认为这应该是一个简单的概念,但在阅读了几个在线网页后,我仍然不太明白。Java字符串如何工作

我不明白Java字符串是如何“不可变的”。目前,我有以下代码:

public static void main(String[] args) { 

    String name = "Jacob Perkins"; 

    System.out.println(name); 

    name = name + "!"; 

    System.out.println(name); 

} 

我的输出如下:

Jacob Perkins 
Jacob Perkins! 

为什么一个字符串应该是这种情况的发生是不可变的?为什么我能够为字符串重新赋值?

+0

'String' * variables *不是不可变的(因为它们是不同的!)您已经创建了一个新的字符串并将其引用赋给了变量'name'。 – dlev 2013-05-08 04:11:12

+0

我还是不明白。为什么我会用Java字符串看到“不可变的”一词? – user2301187 2013-05-08 04:13:04

+0

@ user2301187:两个变量可以指向同一个字符串对象。如果字符串是可变的,则可以通过其他变量的引用来看到一个变量对字符串的更改。因为它们不是,所以每个变量都知道它指向的字符串不能在“它看起来不会改变”的时候改变。这是因为可变字符串会令人感到恐惧并且增加了很多复杂性,例如你必须记得每当你想要一个不会改变的副本的时候就创建一个字符串的副本,或者以后会发生奇怪的事情,这也可能是不安全的事情! – Patashu 2013-05-08 04:15:36

回答

34

让图像解释这个给你:

String example

在左边,你有变量,这实际上是一个参考

  1. String name = "Jacob Perkins;"创建了字符串“Jacob Perkins”,并且name指向它。
  2. name = name + "!";一个新的字符串“Jakob Perkins!”被创建,现在引用指向新的String。但是,旧的不变,因为字符串是不可变的。
+4

+1为视觉:) – renz 2013-05-08 04:23:12

+2

+1图片! – MadProgrammer 2013-05-08 04:24:13

+0

好的,谢谢。我认为视觉帮助。 – user2301187 2013-05-08 04:26:09

1

只有变量引用更改,String对象才是不可变的。

在你的例子中,“雅各布珀金斯”对象依然存在,一个新对象“雅各布珀金斯!”被创建。

name变量指向新对象。

0

实际发生的情况是创建了3个String对象。 “雅各布珀金斯”,“!”和“雅各布帕金斯!”。你没有真正修改“雅各布珀金斯”的例子。您只是将名称变量的引用从“Jacob Perkins”实例更改为“Jacob Perkins!”。

+0

我不明白“改变名称变量的引用”是什么意思。 – user2301187 2013-05-08 04:16:19

+0

在第一个println()中,name变量指向“Jacob Perkins”字符串对象。该对象并没有真正改变,因为字符串是不可变的。相反,创建另外两个新的String对象,“!”和“雅各布帕金斯!”。然后名称变量指向“Jacob Perkins!”。 您实际创建了3个String对象,其中没有一个被静音。 – renz 2013-05-08 04:22:03

0
String name = "Jacob Perkins"; 

String name2 = name + "!"; 
name.substring(5); // or wather syntax is 

那些不改变

5

字符串本身,一旦创建,就不能再改变变量名。你的代码示例确实是与从的以前的内容构建一个字符串和一个惊叹号代替字符串中。 (中原来的内容,这是不再被任何变量引用,最终会被垃圾收集器收获。)

如果你要检查编译后的代码(或通过其与调试步骤)你会发现你的name + "!"表达式已经被编译成了一个StringBuilder对象的创建以及该对象的一些操作。

也就是说,是不可改变的,但变量没有。其值改变,指向不同的字符串。字符串本身从不改变。

0

在Java中有引用和有价值观。

当你说

String foo = "John Smith";

foo是一个变量,保存了一个参考。参考指向包含“John Smith”的对象或值。

该变量保持的引用是可变的。我可以这样做:

foo = "Jack Smith";

而且我已经变异了参考。但是,如果我写这样的代码:

String foo = "John Smith"; 
String bar = foo; //bar's reference is a copy of foo's reference - the same value 
foo = "Jack Smith"; 
System.out.println(bar); //prints John Smith 

我们看到,即使我们改变了富,酒吧并没有改变。为什么?简单地说,当我们写foo = "Jack Smith";时,我们让foo指向一个新的String。我们没有通过foo达到并修改字符串,因为Java中没有任何方法发生变异,或者可以对字符串进行变异。而是返回一个新的字符串,并将该变量指向新的也是不可变的字符串。这样,String变量“指向”的对象永远不能被任何东西修改,只能通过该变量进行修改。这是它保证的Java语言的一个重要属性。

1

也许这会帮助你理解。

假设你有一个类Point(java.awt.Point)。 比方说,你有一个实例号码:

Point p = new Point(0,0); 

然后你让创建一个新的变量y引用同一个物P为:

Point y = p; 

如果你改变p的值,还修改y 。因为类Point是可变的。

p.setLocation(1,1); 

它使得y也引用位置1,1。

使用String类它不会发生。

String a = "123"; 
String b = a; 

如果你使a = a +“4”; a的新值将是“1234”,但b仍然是“123”;

他们所引用的对象没有改变,只是a指向另一个对象。