不可变类:即该类在创建之后其实例变量是不可变的(immutable).
其中有两种特殊情况:
1.不可变类包含的引用类型成员变量是可变类的
2.如果系统需要反复使用相同的不可变类的实例,如果反复创建相同的对象会增加系统的开销,此时考虑使用缓存。
下面代码详细介绍并演示了这两种情况:1.当不可变类包含的引用类型成员变量是可变类的时候,可能造成创建不可变类失败,因此必须保护好可变的引用类型成员变量.
//name类,这是一个可变类
public class Name
{
private String first;
private String last;
public Name(String first,String last)
{
this.first=first;
this.last=last;
}
public void setFirst(String first)
{
this.first=first;
}
public void setLast(String last)
{
this.last=last;
}
public String getFirst()
{
return first;
}
public String getLast()
{
return last;
}
//重写toString方法
public String toString()
{
return last+" "+first;
}
}
//失败的不可变类:当不可变类包含的引用类型成员变量是可变类的时候,可能造成创建不可变类失败
public class MutablePerson
{
private final Name name;
public MutablePerson(Name name)
{
this.name=name;
}
public Name getName()
{
return name;
}
}
/*
不可变的Person类:
当不可变类包含的引用类型成员变量是可变类的时候,可能造成创建不可变类失败,因此必须保护好可变的引用类型成员变量.
*/
public class ImmutablePerson
{
private final Name name;
public ImmutablePerson(Name name)
{
this.name=new Name(name.getLast(),name.getFirst());
}
public Name getName()
{
return new Name(name.getLast(),name.getFirst());
}
}
//测试类
public class ImmutableTest
{
public static void main(String[] args)
{
//Name对象
Name name=new Name("悟空","孙");
MutablePerson mp=new MutablePerson(name);
System.out.println("可变类:"+mp.getName());
name.setFirst("八戒");
System.out.println("可变类:"+mp.getName());
ImmutablePerson ip=new ImmutablePerson(name);
System.out.println(ip.getName());
name.setFirst("悟净");
System.out.println(ip.getName());
System.out.println("可变类:"+mp.getName());
System.out.println(ip.getName());
}
}
2.缓存实例的不可变类:
如果系统需要反复使用相同的不可变类的实例,如果反复创建相同的对象会增加系统的开销,此时考虑使用缓存。Java的Integer类就是利用了缓存机制。
在这篇文章中有详细的介绍:http://blog.csdn.net/sinat_26342009/article/details/44993539
下面利用数组实现一个缓存实例的不可变类:
class CacheImmutableDemo
{
//定义缓存实例的数组
private static final int MAX_SIZE=5; //最多缓存5个实例
private static CacheImmutableDemo[] cache=new CacheImmutableDemo[MAX_SIZE];
//记录缓存实例在缓存中的位置,cache[pos-1]是最新缓存的实例
private static int pos=0;
private final String name;
//私有构造器
private CacheImmutableDemo(String name)
{
this.name=name;
}
public String getName()
{
return name;
}
public static CacheImmutableDemo valueOf(String name)
{
//遍历已缓存的实例
for(int i=0;i<MAX_SIZE;i++)
{
//如果该实例在数组中存在
if(cache[i]!=null&&cache[i].getName().equals(name))
{
//则返回已存在的实例
return cache[i];
}
}
//如果缓存池已满,则
if(pos==MAX_SIZE)
{
//把缓存池的第一个对象覆盖
cache[0]=new CacheImmutableDemo(name);
//把pos设为1
pos=1;
}
//如果缓存池未满
else
{
//把新创建的对象缓存起来,pos+1
cache[pos++]=new CacheImmutableDemo(name);
}
return cache[pos-1];
}
//重写此类的equals和hashCode方法
public boolean equals(Object obj)
{
if(this==obj)
{
return true;
}
if(obj!=null&&obj.getClass()==CacheImmutableDemo.class)
{
CacheImmutableDemo ca=(CacheImmutableDemo)obj;
return name.equals(ca.getName());
}
return false;
}
public int hashCode()
{
return name.hashCode();
}
}
下面是测试类
//测试类
public class CacheImmutableTest
{
public static void main(String[] args)
{
CacheImmutableDemo c1=CacheImmutableDemo.valueOf("test");
CacheImmutableDemo c2=CacheImmutableDemo.valueOf("test");
CacheImmutableDemo c3=CacheImmutableDemo.valueOf("test");
CacheImmutableDemo c4=CacheImmutableDemo.valueOf("test");
CacheImmutableDemo c5=CacheImmutableDemo.valueOf("test");
System.out.println(c1==c5);
}
}