该书介绍了在Java编程中极具实用价值的经验规则,这些经验规则涵盖了大多数开发人员每天所面临的问题的解决方案。通过对Java平台设计专家所使用的技术的全面描述,揭示了应该做什么,不应该做什么才能产生清晰、健壮和高效的代码。
每天下班花点时间学习下吧,尽量在一个星期内把它看完,总结出来,大多数内容都来自书上,个人觉得该书不错的地方摘出来。
第一条:考虑用静态工厂方法代替构造函数
静态工厂方法(优点):
1.每次调用的时候,不一定要创建一个新的对象,这个可以自由控制。
2.它可以返回一个原返回类型的子类型的对象。
第二条:使用私有构造函数强化singleton属性
第一种:提供共有的静态final域
public class Elvis{
public static final Elvis INSTANCE = new Elvis();
private Elvis(){
}
}
第二种:提供一个共有的静态工厂方法
1public class Elvis{
2 private static final Elvis INSTANCE = new Elvis();
3 private Elvis(){
4
5 }
6
7 public static Elvis getInstance(){
8 return INSTANCE;
9 }
10
11}
第一种性能上会稍微好些
第二种提供了灵活性,在不改变API的前提下,允许我们改变想法,把该类做成singleton,或者不做,容易被修改。
注意点:为了使一个singleton类变成克序列花的(Serializable),仅仅在声明中加上implements Serializable是不够的,
为了维护singleton性,必须也要提供一个
private Object readResolve() throws ObjectStreamException{
return INSTANCE;
}
第三条:通过私有构造函数强化不可实例化的能力
只要让这个类包含单个显式的私有构造函数,则它就不可被实例化;
1 public class UtilityClass{
2 private UtilityClass(){
3
4 }
5
6 }
企图通过将一个类做成抽象类来强制该类不可被实例化,这是行不通的。该类可以被子类化,并且该子类也可以被实例化。
更进一步,这样做会误导用户,以为这种类是专门为了继承而设计的。
第四条:避免创建重复的对象
String s = new Sting("silly");//这么恶心的代码就不要写啦。。。
1.静态工厂方法可几乎总是优先于构造方法;Boolean.valueOf(...) > Boolean(...),构造函数每次被调用的时候都会创建一个新的对象,
而静态工厂方法从来不要求这样做。
2.
public class Person {
private final Date birthDate;
public Person(Date date){
this.birthDate = date;
}
//don't do this
public boolean isBabyBoomer(){
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946,Calendar.JANUARY,1,0,0,0);
Date boomStart = gmtCal.getTime();
gmtCal.set(1965,Calendar.JANUARY,1,0,0,0);
Date boomEnd = gmtCal.getTime();
return birthDate.compareTo(boomStart) >=0 && birthDate.compareTo(boomEnd) <0;
}
}
isBabyBoomer每次被调用的时候,都会创建一个新的Calendar,一个新的TimeZone和两个新的Date实例。。。
下面的版本避免了这种低效率的动作,代之以一个static 块初始化Calendar对象,而且最体现效率的是,他的生命周期只实例化一次Calendar并且把
80年,90年的出生的值赋值给类静态变量BOOM_START和BOOM_END
class Person {
private final Date birthDate;
public Person(Date birthDate) {
this.birthDate = birthDate;
}
private static final Date BOOM_START;
private static final Date BOOM_END;
static {
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1980, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1990, Calendar.JANUARY, 1, 0, 0, 0);
BOOM_END = gmtCal.getTime();
}
public boolean isBabyBoomer() {
return birthDate.compareTo(BOOM_START) >= 0
&& birthDate.compareTo(BOOM_END) < 0;
}