在編程中,用final變量來聲明一些常量,這樣就不用在每個用到這個常量數字的地方打入令人厭煩的復雜數字(比如PI),只要打入這個常量名字就行了。這大家都知道,可是要注意,這種常量是在編譯階段才被替換的(所謂替換,就是把程序中用到這個常量名字的地方,用常量本身來替代)。那意味著,如果其它類用到了這個常量,如果常量的值發生了更改,那用到這個常量的類必須重新build一下,否則那個類里還是以前的值。
如果在程序中你用到了private final static常量,并且只在某一個方法內用到,那么你應該把它的聲明移到方法以內。如果被兩個以上的方法用到,那么還是留在類聲明里。
移入方法內部后,不用寫private關鍵字,而且程序看起來比較簡單。
Final Variables
首先寫個例子
public static String someMethod(final String environmentKey){
final String key = "env." + environmentKey;
System.out.println("Key is :" + key);
return (System.getProperty(key));
}
在method中聲明的final變量和常量是不同的,不同之處在于method-scoped final variables are variable。每次進入這個方法內部,這個變量就被初始化一次。當然,這些變量都是運行時進行替換,而不像常量是在編譯時進行替換。
Final Parameters
將方法的parameters聲明成final,可以防止,在方法體內部這個參數被篡改。很好的best practice。
Final Collections
public final static Set VALID_COLORS; 這句語句是不是聲明了一個final set?答案是NO。這只是聲明了一個final引用,也就是VALID_COLORS這個引用不能被更改。
如果重新聲明一個引用指向這個對象,那么這個對象還是能夠更改的,所以這并不是一個final set。那么怎樣做才能真正得到一個final set呢?
public final static Set VALID_COLORS;
static{
Set temp = new HashSet();
temp.add(Color.red);
temp.add(Color.blue);
...
VALID_COLORS = Collections.unmodifiableSet(temp);
}
在實現自己的unmodifiable collections factory的時候,除了要實現Collection,seriallizable接口以外,對于Collection中定義的寫操作,要重載。方法體中可以簡單地拋出UnsupportedOperationException異常。
Instance-Scoped Variables
說白了,就是那些在對象被實例化的時候才被初始化的屬性,并且是不能被修改的。那么就把他聲明成final吧。
ex:private final Date creationDate =
Calendar.getInstance(TimeZone.getTimeZone("GMT")).getTime();
這么做的話,就可以防止誤操作,改變這個本來不應該變的值。
Final Classes
ex:
public final class SomeClass(){
//...Class contents
}
這樣的class 不能被繼承。
還有一種方法實現,就是把它所有的構造函數都改成private的。
這在設計模式中sigleton模式中見過,但這就限制了這個類的重用,所以取個折衷,可以把構造函數聲明成protected的。
Final Method
這個很熟悉了,一個類中的某個方法如果被聲明成final的,那么這個類的子類是不能override這個方法的。
Conditional Complilation
編程的時候我們常常會使用System.out.println(".....");來顯示一些程序的運行情況,但在真正交付的時候,我們并不希望這些語句被編譯到class文件里面去。
一個做法是所有這種類型的語句前面加上一個if(booleanParameter),然后通過設置這個booleanParameter來實現要不要運行這些語句,編譯器在編譯的時候如果發現if里面的語句不可達,那么會將這些程序代碼直接去掉。
疑問就是這些booleanParameter放在哪里比較好和方便。作者給出的建議是在包中專門建一個類,里面存放這些靜態的boolean常量,當然,命名的時候要仔細。名字要指出用在哪里。