如果String
在Java中是不可变的,那么我们如何写为:
String s = new String();
s = s + "abc";
答案 0 :(得分:8)
字符串是不可变的。
这意味着String
的实例无法更改。
您正在更改s
变量以引用其他(但仍然不可变的)String
实例。
答案 1 :(得分:7)
您的字符串变量不是字符串。它是String实例的参考。
亲眼看看:
String str = "Test String";
System.out.println( System.identityHashCode(str) ); // INSTANCE ID of the string
str = str + "Another value";
System.out.println( System.identityHashCode(str) ); // Whoa, it's a different string!
str变量指向的实例是单独不可变的,但该变量可以指向您想要的任何String实例。
如果您不希望将str重新指定为指向其他字符串实例,请将其声明为final:
final String str = "Test String";
System.out.println( System.identityHashCode(str) ); // INSTANCE ID of the string
str = str + "Another value"; // BREAKS HORRIBLY
答案 2 :(得分:2)
第一个答案绝对正确。你应该把它标记为已回答。
s = s+"abc"
不会附加到s对象。它创建一个新的字符串,其中包含s对象(其中没有)和“abc”中的字符。
如果字符串是可变的。它会有像append()这样的方法以及StringBuilder和StringBuffer上的其他类似的变异方法。
Josh Bloch的有效Java对不可变对象及其价值进行了很好的讨论。
答案 3 :(得分:1)
不可变类是那些方法可以改变其字段的类,例如:
Foo f = new Foo("a");
f.setField("b"); // Now, you are changing the field of class Foo
但是在不可变类中,例如字符串,您无法在创建对象后更改对象,但当然,您可以将引用重新分配给另一个对象。例如:
String s = "Hello";
s.substring(0,1); // s is still "Hello"
s = s.substring(0,1); // s is now referring to another object whose value is "H"
答案 4 :(得分:0)
String s = new String();
创建一个新的,不可变的空字符串,变量“s”引用它。
s = s+"abc";
创建一个新的,不可变的字符串;空字符串和“abc”的串联,变量“s”现在引用这个新对象。
答案 5 :(得分:0)
只是澄清,当你说s = s +“abc”时; 这意味着,创建一个新的String实例(由s和“abc”组成),然后将新的String实例分配给s。所以s中的新引用与旧引用不同。
请记住,变量实际上是对某个特定内存位置的对象的引用。即使您更改变量以引用其他位置的新对象,该位置的对象也会保留在该位置。
答案 6 :(得分:0)
String s = new String();
创建一个空的String
对象(""
)。变量s
引用该对象。
s = s + "abc";
"abc"
是一个字符串文字(它只是一个String
对象,它是隐式创建并保存在字符串池中的,因此可以重用它(因为字符串是不可变的,因此是不变的。但是当你new String()
完全不同时,因为你明确地创建了对象,所以不会在池中结束。你可以通过一个叫做实习的东西扔进游泳池。
所以,s + "abc"
因为此时和空字符串(""
)和"abc"
的连接并没有真正创建新的String
对象,因为最终结果为{ {1}}已经在池中。因此,最后变量"abc"
将引用池中的文字s
。
答案 7 :(得分:-2)
我相信你们所做的一切都比它需要的复杂得多,而这只会让想要学习的人感到困惑!
在Java中使对象不可变的主要好处是它可以通过引用传递(例如,传递给另一个方法或使用赋值运算符分配),而不必担心对象的下游更改导致当前方法或上下文中的问题。 (这与关于对象的线程安全性的任何对话非常不同。)
为了说明,创建一个将String作为参数传递给单独方法的应用程序,并修改该方法中的String。在被调用方法的末尾打印String,然后在控制返回到调用方法之后。字符串将具有不同的值,这是因为它们指向不同的内存位置,这是“更改”不可变字符串的直接结果(创建新指针并将其指向幕后的新值)。然后创建一个执行相同操作的应用程序,除了StringBuffer,它不是不可变的。 (例如,您可以附加到StringBuffer来修改它。)打印的StringBuffers将具有相同的值,这是因为它是(a)通过引用传递,因为Java将所有对象作为参数传递给方法, (b)可变。
我希望这能帮助正在阅读这个主题并尝试学习的人们!