不可變類
不可變類的意思是在創(chuàng)建該類的實(shí)例后熔恢,該實(shí)例的實(shí)例變量是不可以改變的。Java提java.lang.String
類都是不可變類健民,當(dāng)創(chuàng)建它們的實(shí)例后柳恐,實(shí)例的實(shí)例變量也是不可改變的。
如:
Double d = new Double(2.2);
String str = new String("cuzz");
如果需要創(chuàng)建一個(gè)自定義的不可變類狸捕,應(yīng)具備以下幾個(gè)規(guī)則
- 使用
private
和final
修飾符來修飾該類的成員變量 - 提供帶參數(shù)的構(gòu)造器喷鸽,用于根據(jù)傳入?yún)?shù)來初始化類里的成員變量
- 提供
getter
方法,不需要setter
方法
下面定義一個(gè)不可變Adress
類灸拍,程序把Address
類的detail和postCode成員變量都使用private隱藏起來做祝,并使用final修飾這兩個(gè)成員變量,不允許其他方法修改這兩個(gè)成員變量的值
public class Address {
private final String detail;
private final String postCode;
// 在構(gòu)造器里初始化兩個(gè)實(shí)例變量
public Address() {
this.detail = "";
this.postCode = "";
}
public Address(String detail, String postCode) {
this.detail = detail;
this.postCode = postCode;
}
// 僅為兩個(gè)實(shí)例變量提供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;
// 當(dāng)detail和postCode同時(shí)相等時(shí)
if (address.detail == detail && address.postCode == postCode) {
return true;
}
}
return false;
}
public int hashCode() {
return detail.hashCode() + postCode.hashCode() * 31;
}
}
緩存實(shí)例的不可變類
不可變類的實(shí)例狀態(tài)不可以改變鸡岗,可以很方便的被多個(gè)對象所共享混槐,如果程序經(jīng)常需要使用相同的不可變實(shí)例,可以考慮緩存這種不可變的實(shí)例轩性。
public class CacheImmutable {
private static int MAX_SIZE = 10;
// 使用數(shù)組來緩存已有的實(shí)例
private static CacheImmutable[] cache = new CacheImmutable[MAX_SIZE];
// 記錄緩存實(shí)例在緩存的位置 cache[pos-1]是最新的實(shí)例
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++) {
// 如果已有相同的實(shí)例 則返回該緩存的實(shí)例
if (cache[i] != null && cache[i].getName().equals(name)) {
return cache[i];
}
}
// 如果緩存池已滿
if (pos == MAX_SIZE) {
// 把緩存的第一個(gè)對象覆蓋 把剛剛生成的對象放在緩存池最開始
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
}
}