【第4条:通过私有构造器强化不可实例化的能力】
这一章很简短,实际上就是告诉我们两件事。
1、一些工具类(utilly class),不希望被实例化的。
2、一些工具类(utilly class),不希望被子类实现的。
为了避免这两个问题,我们可以创造一个【私有构造器】。
没有私有构造器之前:
public class Uitl {
public static boolean IsEmail(String checkStr){
Pattern pattern = Pattern.compile("^[a-z0-9A-Z]+(@)(qq|sina|163|126)\\.(com|cn)$");
Matcher matcher = pattern.matcher(checkStr);
return matcher.matches();
}
public static boolean IsPhoneNum(String checkStr){
Pattern pattern = Pattern.compile("^1(\\d){10}$");
Matcher matcher = pattern.matcher(checkStr);
return matcher.matches();
}
}
继承和实例化都是ok的,这样会给人一种误解,实际上写这些工具类的人是不希望调用者这么做的。
public class ExtendsBean extends Uitl {
//...to do something
}
Uitl uitl = new Uitl();
创造一个私有构造器:
public class Uitl {
private Uitl() {
}
public static boolean IsEmail(String checkStr){
Pattern pattern = Pattern.compile("^[a-z0-9A-Z]+(@)(qq|sina|163|126)\\.(com|cn)$");
Matcher matcher = pattern.matcher(checkStr);
return matcher.matches();
}
public static boolean IsPhoneNum(String checkStr){
Pattern pattern = Pattern.compile("^1(\\d){10}$");
Matcher matcher = pattern.matcher(checkStr);
return matcher.matches();
}
}
这个时候继承会出现错误,同时也没有办法实例化的:
Implicit super constructor Uitl() is not visible for default constructor. Must define an explicit constructor。
这样做,可以清晰的表达编写代码的作者工具类的意义,也避免了调用者的误解。
【第5条:避免创建不必要的对象】
开篇提到了一个常见面试题:
String str = new String("abc"); // DON'T DO THIS
一般在面试题中会问到,这个到底创建了几个对象?实际上就是两个。
一个是new 关键字创建的String实例,一个是“abc”本身就是一个实例。
改进之后:String str ="abc";
我们看另外一个例子,关于Date对象的。
优化前:
public class Person {
private final Date birthDate;
public Person(Date birthDate) {
this.birthDate = birthDate;
}
/**
* 每次调用的时候都会创建
* 一个Calendar、一个TimeZone、两个Date 对象
* 这样是很不好的
* @return
*/
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;
}
}
优化后:
public class Person {
private final Date birthDate;
private static Date boomStart;
private static Date boomEnd;
public Person(Date birthDate) {
this.birthDate = birthDate;
}
/**
* 在person初始化的时候创建一次就行
* @return
*/
static{
Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
gmtCal.set(1946, Calendar.JANUARY,1,0,0,0);
boomStart = gmtCal.getTime();
gmtCal.set(1965, Calendar.JANUARY,1,0,0,0);
boomEnd = gmtCal.getTime();
}
public boolean isBabyBoomer(){
return birthDate.compareTo(boomStart)>=0&&birthDate.compareTo(boomEnd)<=0;
}
}
再来看一个例子:
public static void main(String[] args) {
/*
* 每次在做sum += i运算的时候就会创建一个Long对象
* 也就是因为long变成了Long导致创建了2的31次方个的Long实例
*/
Long sum = 0L;
for (int i = 0; i < Integer.MAX_VALUE; i++) {
sum += i;
}
}
同理我们看看String的例子:
优化前:
public static void main(String[] args) {
String str = "";
str += "a";// str = str +"a";其中 str+"a" 就是一个新对象
str += "b";// str = str +"b";其中 str+"b" 就是一个新对象
str += "c";// str = str +"c";其中 str+"c" 就是一个新对象
str += "d";// str = str +"d";其中 str+"d" 就是一个新对象
System.out.println(str);
}
优化后:
public static void main(String[] args) {
StringBuilder str = new StringBuilder();
str.append("a");
str.append("b");
str.append("c");
str.append("d");
System.out.println(str);
}
总结:
调优很重要的一部分就是对对象、内存的管理,我们写代码的时候要养成习惯,尽量不要产生多余不必要的对象去占用内存空间。