12

我试图准确地理解 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!

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

4

7 回答 7

35

让一张图为你解释一下:

字符串示例

在左侧,您有变量,它实际上是一个引用

  1. String name = "Jacob Perkins;"字符串“Jacob Perkins”被创建并name指向它。
  2. name = name + "!";新字符串“Jakob Perkins!” 已创建,并且引用现在指向新的字符串。然而,旧的保持不变,因为 String 是不可变的。
于 2013-05-08T04:22:44.280 回答
5

字符串本身一旦创建,就永远无法更改。您的代码示例所做的是将name中的字符串替换为从name的先前内容和感叹号构造的新字符串。name的原始内容,不再被任何变量引用,最终将被垃圾收集器回收。)

如果您要检查已编译的代码(或使用调试器单步执行),您会发现您的name + "!"表达式已被编译为 StringBuilder 对象的创建和对该对象的一些操作。

也就是说,字符串是不可变的,但变量 不是。它的值发生变化,指向不同的字符串。琴弦本身永远不会改变。

于 2013-05-08T04:16:57.517 回答
1

String 对象是不可变的,只有变量引用发生变化。

在您的示例中,“Jacob Perkins”对象仍然存在,并且有一个新对象“Jacob Perkins!” 被创建。

name 变量指向新对象。

于 2013-05-08T04:12:06.077 回答
1

也许这会帮助你理解。

假设您有一个类 Point (java.awt.Point)。假设您有一个实例 p:

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 现在指向另一个对象。

于 2013-05-08T04:28:49.713 回答
0

实际发生的是创建了 3 个 String 对象。“雅各布·帕金斯”、“!” 和“雅各布·帕金斯!”。您并没有真正修改“Jacob Perkins”实例。您刚刚将 name 变量的引用从“Jacob Perkins”实例更改为“Jacob Perkins!”。

于 2013-05-08T04:12:44.643 回答
0
String name = "Jacob Perkins";

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

那些不会改变变量名

于 2013-05-08T04:14:33.540 回答
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,bar 也没有改变。为什么?简单地说,当我们写的时候,foo = "Jack Smith";我们让 foo 指向一个新的字符串。我们没有通过 foo 来修改字符串,因为Java 中没有方法发生变异,或者可以变异字符串。而是返回一个新的字符串,并使变量指向新的、同样不可变的字符串。这样,字符串变量“指向”的对象永远不能被任何东西修改,只能通过该变量。这是它保证的 Java 语言的一个重要属性。

于 2013-05-08T04:23:41.700 回答