参考不可变类String的设计,说明一下不可变设计的要素
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
/** Cache the hash code for the string */
private int hash; // Default to 0
//其它方法...
}
final的使用
发现该类、类中所有属性都是 final 的
- 属性用 final 修饰保证了该属性只读,不能修改,一旦设置值就不可再改变。
- 类用 final 修饰保证了该类中的方法不能被覆盖,防止子类无意间破坏不可变性,final 修饰的类实际上不可以被继承。
保护性拷贝
字符串类,当比较两个字符串是否相等时,如果直接用“=”比较,那么比较的是字符串引用,常说的字符串一旦定义就不可变,指的是类对象中的 private final char value[]是不变的,只有一份,如果调用substring方法,字符型数组value值仍不变,substring内部相当于再创建一个全新的String类对象返回。
String类-substring方法源码:
public String substring(int beginIndex) {
if (beginIndex < 0) {
throw new StringIndexOutOfBoundsException(beginIndex);
}
int subLen = value.length - beginIndex;
if (subLen < 0) {
throw new StringIndexOutOfBoundsException(subLen);
}
return (beginIndex == 0) ? this : new String(value, beginIndex, subLen);
}
保护性拷贝是可以保护线程安全的,例如多个线程调用substring方法,那么实际上不是多个线程对value数组访问操作,而是每个线程均得到一个新的String对象,这从根本上保护了线程安全,因为甚至多个线程访问的不是共享变量,每个线程独有。
注意:不可变类的单个方法是线程安全的,但不能保证方法的组合是线程安全的。