概念:一個非可變性的類是一個簡單的類,每個實例包括的信息都是他在被創建的時候就提供出來的,並且在對象的生命週期內不是不能更改的。這樣的類如:String,BigInteger等等。爲什麼會有這樣的類呢?他們包含了優雅的設計思想:簡單,不可變,穩定。
其實有點很提倡使用非可變類,但是不一定非要使用。
下面創建一個優雅的非可變類的5點:
1.不要提供任何可以修改對象的方法。
2.保證沒有可以被子類修改的方法。可以把方法都修飾成final當然還有其他辦法,下面會提到。
3.所有的域都是final的。
4.所有的域都是私有的。
5.保證對任何可變組件的互斥訪問。其實這個話的意思就是你的非可變類中有域指向可變的引用,你應該讓這個引用不要被修改,也就是不要讓客戶代碼來修改這個引用。並且不要用客戶的對象來初始化你的非可變類。
/**
*
*/
/**
* 非可變性的類,表示複數的類
* @author jayd
*
*/
public class Complex {
private final float re;
private final float im;
public Complex(float re,float im){
this.re=re;
this.im=im;
}
public float realPart(){
return re;
}
public float imaginaryPart(){
return im;
}
public Complex add(Complex c){
return new Complex(re+c.re,im+c.im);
}
public Complex subtract(Complex c){
return new Complex(re-c.re,im-c.im);
}
public Complex multiply(Complex c){
return new Complex(re*c.re-im*c.im,re*c.im+im*c.re);
}
public Complex divide(Complex c){
float tmp=c.re*c.re+c.im*c.im;
return new Complex((re*c.re+im*c.im)/tmp,(im*c.re-re*c.im)/tmp);
}
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Float.floatToIntBits(im);
result = prime * result + Float.floatToIntBits(re);
return result;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Complex other = (Complex) obj;
if (Float.floatToIntBits(im) != Float.floatToIntBits(other.im))
return false;
if (Float.floatToIntBits(re) != Float.floatToIntBits(other.re))
return false;
return true;
}
}
這些複數類提供的加減乘除的方法,這些方法每次都是創建新的實例。一般非可變類都是採用這樣的模式。在運算中不去改變他的域的值或是引用。
非可變類具體好處:比較簡單,每個對象一個狀態,都是在創建的時候就給定了的。
非可變類是線程安全的,他們不需要被安全同步。因爲他們的域是不可能改變的,都是在創建的時候就給定了。所以非可變對象是可以被多個線程共享的。但是在這裏,我們就發現我們可能在實際中會使用到很多重用的實例對象,我們可以使用靜態存儲區把他們放進去緩存起來。我也可以學習BigInteger和Boolean類的做法,提供一個靜態工廠方法可以做到單例或是緩存的作用。
非可變類的一個比較多的應用就是用來給其他類提供大量構件的服務。比如說map的常量類,這個估計做過系統的人都知道,就是把一些常量定義起來在一個類中。但是非可變類唯一的缺點就是每次都要實例新的對象。