Final constrants
在编程中,用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常量,当然,命名的时候要仔细。名字要指出用在哪里。