我试图准确理解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 :(得分:34)
让图像为您解释:
在左侧,您有变量,实际上是参考。
String name = "Jacob Perkins;"
创建字符串“Jacob Perkins”,name
指向它。name = name + "!";
一个新的字符串“Jakob Perkins!”已创建,引用现在指向新String。但是,旧版本保持不变,因为String是不可变的。答案 1 :(得分:5)
字符串本身一旦创建,就永远无法更改。您的代码示例所执行的操作是将名称中的字符串替换为 new 字符串,该字符串是根据 name <的先前内容构建的/ strong>,还有一个感叹号。 ( name 的原始内容,不再被任何变量引用,最终将由垃圾收集器获取。)
如果您要检查已编译的代码(或使用调试器逐步执行它),您会发现已将name + "!"
表达式编译为StringBuilder对象的创建以及该对象上的一些操作。
也就是说,字符串是不可变的,但变量 名称不是。它的值会发生变化,指向不同的字符串。字符串本身永远不会改变。
答案 2 :(得分:1)
只有变量引用发生变化,String对象才是不可变的。
在你的例子中,“Jacob Perkins”对象仍然存在,一个新对象“Jacob Perkins!”得到了。
name变量指向新对象。
答案 3 :(得分: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现在指向另一个对象。
答案 4 :(得分:0)
实际发生的是创建了3个String对象。 “Jacob Perkins”,“!”和“雅各布珀金斯!”你没有真正修改“Jacob Perkins”实例。您刚刚更改了名称变量的引用,从“Jacob Perkins”实例更改为“Jacob Perkins!”。
答案 5 :(得分:0)
String name = "Jacob Perkins";
String name2 = name + "!";
name.substring(5); // or wather syntax is
那些不会更改变量名称
答案 6 :(得分: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指向一个新的String。我们没有通过foo到达并修改字符串,因为 Java中没有方法变异,或者可以改变字符串。而是返回一个新的String,并使变量指向新的,也是不可变的String。这样,String变量'points'的对象永远不会被任何东西修改,只能通过该变量。这是它所保证的Java语言的一个重要属性。