第二章第四条和第五条经验
通过私有化构造器强化不可实例化的能力
避免创建不必要的对象
私有化构造器,强化不可实例化能力
对于工具类,只有静态域或者静态方法,对这种类实例化毫无意义,所以需要避免让使用者能够实例化这种类。如果只通过把该类作为抽象类来强制该类不可实例化,这是行不通的。该类可以被子类化并且子类也可以被实例化。并且这样做还可能误导用户,以为这种类是专门为了继承而设计的。因此需要显式的声明无参构造器,并私有化,方法抛出异常。
public class UtilityClass {
private UtilityClass() {
throw new AssertionErron();
}
}
副作用
由于该类没有外部可调用的构造器,所以使得该类不能被子类化。
避免创建多余的对象
一般来说,最好能重用对象,避免每次都创建功能相同的对象。如果对象是不可变的,则可以始终被重用。
//不要这样做
String s = new String("stringetee");
改进后
String s = "stringetee";
对于同一台虚拟机种运行的代码,只要它们包含相同的字符串字面常量,该对象就会被重用。
两个例子
除了重用不可变的对象之外,也可以重用那些已知不会被修改的可变对象;
public class Person{
private final Date birthDate;
//不要这样做,每次调用都会新建一个Calendar、一个TimeZone和两个Date对象
public boolean isBabyBoomer(){
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimemZone("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 ;
}
}
重构后:
class Person{
private final Date birthDate;
private static final Date BOOM_START;
private static final Date BOOM_END;
//使用静态的初始化器,只在Person类加载是创建一次这些对象
static{
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946,Calendar.JANUARY,1,0,0,0);
BOOM_START = gmtCal.getTime();
gmtCal.set(1965,Calendar.JANUARY,1,0,0,0);
BOOM_END = gmtCal.getTime();
}
public boolean isBabyBoomer(){
return birthDate.compareTo(BOOM_START ) >= 0 &&
birthDate.compareTo(BOOM_END ) < 0 ;
}
}