不可变类的实例的状态不会变化这样的实例可以安全地被其他与之关联的对象共享还可以安全地被多个线程共享为了节省内存空间优化程序的性能应该尽可能地重用不可变类的实例避免重复创建具有相同属性值的不可变类的实例
在JDK 的基本类库中对一些不可变类如Integer类做了优化它具有一个实例缓存用来存放程序中经常使用的Integer实例JDK 的Integer类新增了一个参数为int类型的静态工厂方法valueOf(int i)它的处理流程如下
if(在实例缓存中存在取值为i的实例)
直接返回这个实例
else{
用new语句创建一个取值为i的Integer实例
把这个实例存放在实例缓存中
返回这个实例
}
在以下程序代码中分别用new语句和Integer类的valueOf(int i)方法来获得Integer实例
Integer a=new Integer();
Integer b=new Integer();
Integer c=IntegervalueOf();
Integer d= IntegervalueOf();
Systemoutprintln(a==b); //打印false
Systemoutprintln(a==c); //打印false
Systemoutprintln(c==d); //打印true
以上代码共创建了个Integer对象每个new语句都会创建一个新的Integer对象而IntegervalueOf()方法仅在第一次被调用时创建取值为的Integer对象在第二次被调用时直接从实例缓存中获得它由此可见在程序中用valueOf()静态工厂方法获得 Integer对象可以提高Integer对象的可重用性
到底如何实现实例的缓存呢?缓存并没有固定的实现方式完善的缓存实现不仅要考虑何时把实例加入缓存还要考虑何时把不再使用的实例从缓存中及时清除以保证有效合理地利用内存空间一种简单的实现是直接用Java集合来作为实例缓存
下面的例程它拥有实例缓存和相应的静态工厂方法valueOf()Name类的实例缓存中可能会加入大量Name对象为了防止耗尽内存在实例缓存中存放的是Name对象的软引用(SoftReference)如果一个对象仅仅持有软引用Java虚拟机会在内存不足的情况下回收它的内存
例程 Namejava
import javautilSet;
import javautilHashSet;
import javautilIterator;
import javalangref*;
public class Name {
…
//实例缓存存放Name对象的软引用
private static final Set> names=new HashSet>();
public static Name valueOf(String firstname String lastname){ //静态工厂方法
Iterator> it=namesiterator();
while(ithasNext()){
SoftReference ref=itnext();//获得软引用
Name name=refget();//获得软引用所引用的Name对象
if(name!=null&& namefirstnameequals(firstname)&& namelastnameequals(lastname))
return name;
}
//如果在缓存中不存在Name对象就创建该对象并把它的软引用加入到实例缓存
Name name=new Name(firstnamelastname);
namesadd(new SoftReference(name));
return name;
}
public static void main(String args[]){
Name n=NamevalueOf(小红王);
Name n=NamevalueOf(小红王);
Name n=NamevalueOf(小东张);
Systemoutprintln(n);
Systemoutprintln(n);
Systemoutprintln(n);
Systemoutprintln(n==n); //打印true
}
}
在程序中既可以通过new语句创建Name实例也可以通过valueOf()方法创建Name实例在程序的生命周期中对于程序不需要经常访问的 Name实例应该使用new语句创建它使它能及时结束生命周期;对于程序需要经常访问的Name实例那就用valueOf()方法来获得它因为该方法能把Name实例放到缓存中使它可以被重用