String s = "Hello";
s += " world!";
这两行代码执行之后,原始的String对象中的内容到底有没有改变。
答案是,没有改变。因为String 被设计成不可变的(immutable)类,所以他的所有对象都是不可变的对象。在这段代码中,s原先指向一个String对象,内容是“Hello”,然后我们对s进行了“+”拼接操作,这时,s就不指向原来的那个对象了,而是指向了另一个String对象,内容为“Hello world!”,原来的那个对象还存在于内存中,只是这个s的引用不再指向它了。
String s = "Hello";
System.out.println(s.hashCode());
s+=" world!";
System.out.println(s.hashCode());
通过上面的说明,我们很容易得到 一个结论,如果经常对字符串进行各式的修改,或者说是不可预见的修改,那么使用String 来代表字符串的话就会引起很大的开销。因为String 对象建立之后不能在改变,所以对于每个不同的字符串,都需要一个String 对象来表示。这时,我们就应该考虑使用StringBuffer类,这个类允许修改,而不是每个字符串都需要生成一个新的对象。并且这两个类的转换很简单。
其实不只 String,很多 Java 标准类库中的类都是不可变的。在开发一个系统的时候,我们有时候也需要设计不可变类,来传递一组相关的值,这也是面向对象思想的体现。不可变类有一些优点,比如因为它的对象是只读的,所以多线程并发访问也不会有任何问题。当然也有一些缺点,比如每个不同的状态都要一个对象来代表,可能会造成性能上的问题。所以 Java 标准类库还提供了一个可变版本,即 StringBuffer。