- 不变对象是一旦创建,就只能表示相同的值,譬如String对象。
- 可变对象是能够改变对象的值,譬如StringBuidler。
如下例子:
String s = "a";
s = s.concat("b");
StringBuilder sb = new StringBuilder("a");
sb.append("b");
如果是多个字符相连:
StringBuilder的效率要高于String的
如下程序时间复杂度为O(N^2):
String s = "";
for (int i = 0; i < n; ++i) {
s = s + n;
}
如下程序时间复杂度为O(N):
StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; ++i) {
sb.append(String.valueOf(i));
}
String s = sb.toString();
可变对象的使用效率可能要优于不变对象,但是不变对象易于调试,易于理解,更容易改变。更多时候为了程序出bug,我们一般选用不变对象。
- 可变对象风险示例——传入可变参数:
假设我们要把一个集合中的数字相加,返回结果。从性能和DRY来说:
/** @return the sum of the absolute values of the numbers in the list */
public static int sumAbsolute(List<Integer> list) {
// let's reuse sum(), because DRY, so first we take absolute values
for (int i = 0; i < list.size(); ++i)
list.set(i, Math.abs(list.get(i)));
return sum(list);
}
上述程序直接改变了list,导致list传参到后续的程序,会出现BUG,如:
// meanwhile, somewhere else in the code...
public static void main(String[] args) {
// ...
List<Integer> myData = Arrays.asList(-5, -3, -2);
System.out.println(sumAbsolute(myData));
System.out.println(sum(myData));
}
- 可变对象风险示例——返回可变结果: