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();  
    }  
} 

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值