请说明一下使用具有缓冲的不可变类的好处,并设计一个带有缓存的不可变类。
答:不可变类的实例的状态不会发生变化,这样的实例可以安全地被其他与之相关的对象共享,还可以安全地被多个线程共享。为了节省内存空间,优化程序的性能,应该尽量重用不可变类的实例,避免重复创建具有相同属性值的不可变类的实例。但是值得注意的一点是,没有必要为所有的不可变类提供实例缓存机制。随意地创建大量的实例供缓存,反而会造成不必要的内存开销和降低程序运行的性能。通常只有满足以下几个条件的时候才需要使用不可变类的实例缓存机制:
(1)不可变类的实例数量有限,缓存这些实例的内存开销比较小。
(2)在程序运行过程中,需要频繁地访问不可变类的一些特定的实例。这些实例拥有与程序本身同样长的生命周期。
下面写了一个带有缓存的不可变类的例子,非常简单,只是为了说明如何创建一个带缓存的不可变类。
程序运行的结果是:
Lab-Computer-0db2f6:JavaExercises labuser$ javac Name.java
Lab-Computer-0db2f6:JavaExercises labuser$ java Name
Name@635b9e68
Name@635b9e68
Name@13fcf0ce
true
Lab-Computer-0db2f6:JavaExercises labuser$
运行结果的最后一行返回了true,说明了缓存机制其作用了,使用了在缓存中的一个对象。
答:不可变类的实例的状态不会发生变化,这样的实例可以安全地被其他与之相关的对象共享,还可以安全地被多个线程共享。为了节省内存空间,优化程序的性能,应该尽量重用不可变类的实例,避免重复创建具有相同属性值的不可变类的实例。但是值得注意的一点是,没有必要为所有的不可变类提供实例缓存机制。随意地创建大量的实例供缓存,反而会造成不必要的内存开销和降低程序运行的性能。通常只有满足以下几个条件的时候才需要使用不可变类的实例缓存机制:
(1)不可变类的实例数量有限,缓存这些实例的内存开销比较小。
(2)在程序运行过程中,需要频繁地访问不可变类的一些特定的实例。这些实例拥有与程序本身同样长的生命周期。
下面写了一个带有缓存的不可变类的例子,非常简单,只是为了说明如何创建一个带缓存的不可变类。
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.lang.ref.*;
public class Name{
private String firstName;
private String lastName;
private static final Set<SoftReference<Name>> names=
new HashSet<SoftReference<Name>>();
public Name(String firstName,String lastName){
this.firstName=firstName;
this.lastName=lastName;
}
public static Name valueOf(String firstName,String lastName){
Iterator<SoftReference<Name>> it=names.iterator();
while(it.hasNext()){
SoftReference<Name> ref = it.next();
Name name = ref.get();
if(name!=null
&& name.firstName.equals(firstName)
&& name.lastName.equals(lastName)){
return name;
}
}
Name name = new Name(firstName,lastName);
names.add(new SoftReference<Name>(name));
return name;
}
public static void main(String[] args){
Name n1=Name.valueOf("Xiaohong","Wang");
Name n2=Name.valueOf("Xiaohong","Wang");
Name n3=Name.valueOf("Xiaodong","Zhang");
System.out.println(n1);
System.out.println(n2);
System.out.println(n3);
System.out.println(n1==n2);
}
程序运行的结果是:
Lab-Computer-0db2f6:JavaExercises labuser$ javac Name.java
Lab-Computer-0db2f6:JavaExercises labuser$ java Name
Name@635b9e68
Name@635b9e68
Name@13fcf0ce
true
Lab-Computer-0db2f6:JavaExercises labuser$
运行结果的最后一行返回了true,说明了缓存机制其作用了,使用了在缓存中的一个对象。