一.可变对象与不可变对象
Java中某些对象是可变的(mutable),它们有改变内部值的方法。例如,一个StringBuilder对象有办法来改变字符串内部的字符,等等。
StringBuilder sb = new StringBuilder("a");
sb.append("b");
快照图:
而不可变的对象一旦创建就无法改变(immutable)。例如如果要在一个String对象表示的字符串后面添加字符,只能重新创建一个String对象。
String s = "a";
s = s.concat("b"); // 使用s+="b" 或 s=s+"b"也能达到同样的效果
这段代码看上去与StringBuilder中的append方法相似,但效果不同:由于String对象被创建后就无法更改,所以实际上concat方法重新new了一个String对象让"a" "b"相连,并让s索引到这个对象。
快照图:
二.两者的区别
从结果上来看,使用String或者StringBuilder都让s索引到了一个表示字符串“ab”的对象,那么使用可变对象与不可变对象有什么区别呢?
考虑如下代码:
String s = "a";
String t = s;
s=s.concat("b");
//t=?
t理所当然等于"a"。
但是如果我们用StringBuilder替换String:
StringBuilder sb = new StringBuilder("a");
StringBuilder tb = sb;
sb=tb.append("b");
//tb=?
这时tb表示的字符串变成了"ab"。
为什么出现这种结果?
因为String是不可变对象,s调用方法concat后新创建了一个String对象,让s索引到上面,而t依旧指向原来的对象,所以仍然表示"a"。
而StringBuilder是可变对象,sb调用方法append后直接更改了指向的对象,同样指向该对象的tb表示的字符串也就跟着发生了变化。