不可变类?
是指当创建了这个类的实例后,就不允许修改它的属性值。在JDK的基本类库中,所有基本类型的包装类,如Integer和Long类,都是不可变类,java.lang.String也是不可变类。
如何创建一个不可变类?
1. 所有成员都是private
2. 不提供对成员的改变方法,例如:setXXXX
3. 确保所有的方法不会被重载。手段有两种:使用final Class(强不可变类),或者将所有类方法加上final(弱不可变类)。
4. 如果某一个类成员不是原始变量(primitive)或者不可变类,必须通过在成员初始化(in)或者get方法(out)时通过深度clone方法,来确保类的不可变。
(primitive变量: boolean,byte, char, double ,float, integer, long, short)
下面是一个自定义不可变类的例子:
public final class FinalClass {
private final int[] myArray;
public FinalClass(int[] anArray) {
this.myArray = anArray.clone();
}
public String toString() {
StringBuffer sb = new StringBuffer("Numbers are: ");
for (int i = 0; i < myArray.length; i++) {
sb.append(myArray[i] + " ");
}
return sb.toString();
}
}
不可变类的用途?
不可变类的实例的状态不会变化,这样的实例可以安全地被其他与之关联的对象共享,还可以安全地被多个线程共享。
为了节省内存空间,优化程序的性能,应该尽可能地重用不可变类的实例,避免重复创建具有相同属性值的不可变类的实例。
下面是一个缓存不可变类实例的例子:
package com.basic.finalclass;
import java.lang.ref.SoftReference;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class BasicFinalClass {
public static void main(String argv[]) {
FinalClass m1 = FinalClass.valueOf("a");
FinalClass m2 = FinalClass.valueOf("b");
FinalClass m3 = FinalClass.valueOf("a");
System.out.println(m1.toString());
System.out.println(m2.toString());
System.out.println(m3.toString());
System.out.println(m1 == m3);
}
}
@SuppressWarnings("rawtypes")
final class FinalClass {
private final String type;
private final static int[] myArray = new int[]{1,2,3};
private final static Set<SoftReference> types = new HashSet<SoftReference>();
public FinalClass(String type) {
this.type = type;
}
public String toString() {
StringBuffer sb = new StringBuffer("Type are: " + type + " Numbers are: ");
for (int i = 0; i < myArray.length; i++) {
sb.append(myArray[i] + " ");
}
sb.append(" myArray are: " + myArray);
return sb.toString();
}
@SuppressWarnings("unchecked")
public static FinalClass valueOf(String type) {
Iterator<SoftReference> it = types.iterator();
while (it.hasNext()) {
SoftReference ref = it.next();
FinalClass obj = (FinalClass)ref.get();
if (type != null && obj.type.equals(type)) {
return obj;
}
}
FinalClass obj = new FinalClass(type);
types.add(new SoftReference(obj));
return obj;
}
}
总结:
1)为了防止耗尽内存,在实例缓存中存放的是对象的软引用(SoftReference),如果一个对象仅仅持有软引用,Java虚拟机会在内存不足的情况下回收它的内存
2)在程序的生命周期中,对于程序不需要经常访问的实例,应该使用new语句创建它,使它能及时结束生命周期
3)对于程序需要经常访问的实例,那就用valueOf()方法来获得它,因为该方法能把实例放到缓存中,使它可以被重用
4)只有满足以下条件的不可变类才需要实例缓存
A、不可变类的实例的数量有限
B、在程序运行过程中,需要频繁访问不可变类的一些特定实例。这些实例拥有与程序本身同样长的生命周期
参考:
http://soft.chinabyte.com/database/285/11363785.shtml