Java的不可变类(缓存实例)

不可变类

不可变类的意思是在创建该类的实例后,该实例的实例变量是不可以改变的。Java提java.lang.String类都是不可变类,当创建它们的实例后,实例的实例变量也是不可改变的。

如:

Double d = new Double(2.2);
String str = new String("cuzz");

如果需要创建一个自定义的不可变类,应具备以下几个规则

  • 使用privatefinal修饰符来修饰该类的成员变量
  • 提供带参数的构造器,用于根据传入参数来初始化类里的成员变量
  • 提供getter方法,不需要setter方法

下面定义一个不可变Adress类,程序把Address类的detail和postCode成员变量都使用private隐藏起来,并使用final修饰这两个成员变量,不允许其他方法修改这两个成员变量的值

public class Address {
    private final String detail;
    private final String postCode;
    // 在构造器里初始化两个实例变量
    public Address() {
        this.detail = "";
        this.postCode = "";
    }
    
    public Address(String detail, String postCode) {
        this.detail = detail;
        this.postCode = postCode;
    }
    
    // 仅为两个实例变量提供getter方法
    public String getDetail() {
        return this.detail;
    }
    
    public String getPostCode() {
        return this.postCode;
    }
    
    // 重新equeal方法
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        
        if (obj != null && obj.getClass() == Address.class) {
            Address address = (Address) obj;
            // 当detail和postCode同时相等时
            if (address.detail == detail && address.postCode == postCode) {
                return true;
            }
        }
        return false;
    }
    
    public int hashCode() {
        return detail.hashCode() + postCode.hashCode() * 31;
    }
}

缓存实例的不可变类

不可变类的实例状态不可以改变,可以很方便的被多个对象所共享,如果程序经常需要使用相同的不可变实例,可以考虑缓存这种不可变的实例。

public class CacheImmutable {
    private static int MAX_SIZE = 10;
    // 使用数组来缓存已有的实例
    private static CacheImmutable[] cache = new CacheImmutable[MAX_SIZE];
    // 记录缓存实例在缓存的位置   cache[pos-1]是最新的实例
    private static int pos = 0;
    private final String name;
    
    private CacheImmutable(String name) {
        this.name = name;
    }
    
    private String getName() {
        return name;
    }
    
    public static CacheImmutable 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) {
            // 把缓存的第一个对象覆盖  把刚刚生成的对象放在缓存池最开始
            pos = 0;
            cache[pos++] = new CacheImmutable(name);
        }else {
            cache[pos++] = new CacheImmutable(name);
        }
        return cache[pos-1];
        

    }
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj != null && obj.getClass() == CacheImmutable.class) {
            CacheImmutable ci = (CacheImmutable) obj;
            return name.equals(ci.getName());
        }
        return false;
    }
}

测试类:

public class CacheImmutableTest {
    public static void main(String[] args) {
        CacheImmutable c1 = CacheImmutable.valueOf("cuzz");
        CacheImmutable c2 = CacheImmutable.valueOf("cuzz");
        System.out.println(c1 == c2 );   // 输出true
    }
}

与Java提供的java.lang.Integer类采用的相同的策略

public class IntegerCacheTest {
    public static void main(String[] args) {
        // 生成新的Integer对象
        Integer in1 = new Integer(6);
        // 生成新的Integer对象  并缓存该对象
        Integer in2 = Integer.valueOf(6);
        // 直接从缓存中取出Integer对象
        Integer in3 = Integer.valueOf(6);
        System.out.println(in1 == in2);  // false
        System.out.println(in2 == in3);  // true
        // 由于Integer只缓存-128~127之间
        Integer in4 = Integer.valueOf(200);
        Integer in5 = Integer.valueOf(200);
        System.out.println(in4 == in5);   // false
    }
}

你可能感兴趣的:(Java的不可变类(缓存实例))