Java不可变类和不可变类的作用

什么是不可变类
是指当创建了这个类的实例后,就不允许修改它的属性值。在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();    
    }    
}   

不可变类的用途

不可变类的实例的状态不会变化,这样的实例可以安全地被其他与之关联的对象共享,还可以安全地被多个线程共享。
为了节省内存空间,优化程序的性能,应该尽可能地重用不可变类的实例,避免重复创建具有相同属性值的不可变类的实例。

下面是一个缓存不可变类实例的例子:

public class CacheImmutable//定义了一个不可变类,使用这个类的数组实现
{
 
   //数组来缓存已有的实例
   private static CacheImmutable[] cache=new CacheImmutable[10];
   //设置一个变量来指向数组的偏移量
   private static int pos=0;
   private final String name;
   public CacheImmutable(String name)
   {
	   this.name=name;
   }
   public String getName()
   {
	   return this.name;
   }
   public static CacheImmutable valueOf(String name)
   {  //遍历缓冲池
	   for(int i=0;i<10;i++)
	   {  //如果有相同的实例,直接返回已有实例
		   if(cache[i] !=null && cache[i].getName().equals(name))//这里有可能出现空指针错误,注意格式就行!!!!我调试很很久!!
		   {
			   return cache[i];
		   }
		   //如果已满,则就要把第一个覆盖
		   if(pos==10)
		   {   pos=0;
			   cache[pos++]=new CacheImmutable(name);
		   }
		   //否则就放在最后一个位置
		   else
		   {
			   cache[pos++]=new CacheImmutable(name);
		   }
	   }
	   return cache[pos-1];
   }
   //重写equals方法
   public boolean equals(Object obj)
   {
	   if(this ==obj)
	   {
		   return true;
	   }
	   if(obj!=null&&obj.getClass()==CacheImmutable.class)
	   {
		   CacheImmutable ci =(CacheImmutable)obj;
		   return obj.equals(ci.getName());
	   }
	return false;
   }
   //重写hashCode方法
   public int hashCode()
   {
	   return name.hashCode();
   }
}
public class CacheImmutableText
{ 
	
	public static void main(String[] args) throws NullPointerException//为了避免出空指针错误,这里把错误抛出!!!!
	{ 
	   CacheImmutable c1=CacheImmutable.valueOf("Hello");
	   CacheImmutable c2=CacheImmutable.valueOf("Hello");
	   System.out.println(c1==c2);
	}
}

总结:

1. 为了防止耗尽内存,在实例缓存中存放的是对象的软引用(SoftReference),如果一个对象仅仅持有软引用,Java虚拟机会在内存不足的情况下回收它的内存
2. 在程序的生命周期中,对于程序不需要经常访问的实例,应该使用new语句创建它,使它能及时结束生命周期
3. 对于程序需要经常访问的实例,那就用valueOf()方法来获得它,因为该方法能把实例放到缓存中,使它可以被重用
4. 只有满足以下条件的不可变类才需要实例缓存


A、不可变类的实例的数量有限

B、在程序运行过程中,需要频繁访问不可变类的一些特定实例。这些实例拥有与程序本身同样长的生命周期

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值