第一条:考虑静态工厂方法代替构造器
静态工厂方法的优势:
- 有名称(例子中的probablePrime)
BigInteger b = BigInteger.probablePrime(9, new Random());
- 不必每次调用它们的时候都创建一个新对象
Boolean.valueOf()方法源代码,因为只有两种状态,所有先声明两个public static final 的Boolean对象,调用的时候就不会有对象的实例化过程了。
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
- 可以返回类型的任何子类型
暂时还无法理解
- 使代码更加简洁
import java.util.HashMap;
public class Test {
public static void main(String[] args) {
HashMap<String, String> hashMap = MyHashMap.newInstance();
hashMap.put("name", "Sherlock Moon");
System.out.println(hashMap.get("name"));
}
static class MyHashMap<K, V> extends HashMap<K, V> {
private static final long serialVersionUID = 1L;
public static <K, V> HashMap<K, V> newInstance() {
return new HashMap<K, V>();
}
}
}
静态工厂方法的劣势
类如果不含公有的或者受保护的构造器,就不能被子类化。
它们与静态方法没有区别,难以分清。解决办法:
统一方法名:valueOf : 返回的实例与参数值相同,比如:String.valueOf()。
of : valueOf的替代。
getInstance : 没有参数,返回唯一的实例。如Calendar.getInstance。
newInstance :返回的实例和所有其他的实例不同。
getType :和getInstance一样,Type表示工厂方法所返回的对象类型。
newType :和newInstance一样。
* 第二条:遇到多个构造器参数时要考虑用构建器
package test;
public class Student {
private final Long userId;
private final String userPassword;
private String userEmail = null;
public static void main(String[] args) {
Student s = new Student.Builder(123456L, "xxxyyyzzz").email("1@2.com").build();
System.out.println(s.toString());
}
private Student(Builder builder) {
this.userEmail = builder.userEmail;
this.userId = builder.userId;
this.userPassword = builder.userPassword;
}
public static class Builder {
private final Long userId;
private final String userPassword;
private String userEmail;
public Builder(Long userId, String userPassword) {
this.userId = userId;
this.userPassword = userPassword;
}
public Builder email(String val) {
this.userEmail = val;
return this;
}
public Student build() {
return new Student(this);
}
}
@Override
public String toString() {
return "userName : " + this.userId
+ "\nuserPassword : " + this.userPassword
+ "\nuserEmail : " + this.userEmail;
}
}
/*
userName : 123456
userPassword : xxxyyyzzz
userEmail : 1@2.com
*/
* 第三条:用私有构造器或者枚举类型强化Singleton属性
public class SingletonTest {
public final static int DEFAULT_WIDTH = 10;
public final static int DEFAULT_HEIGHT = 10;
private int width;
private int height;
private final static SingletonTest INSTANCE = new SingletonTest(DEFAULT_WIDTH, DEFAULT_HEIGHT);
private SingletonTest(int width, int height) {
this.width = width;
this.height = height;
}
public static SingletonTest getInstance() {
return INSTANCE;
}
@Override public String toString() {
return "width : " + this.width
+ "\nheight : " + this.height;
}
public static void main(String[] args) {
SingletonTest s = SingletonTest.getInstance();
System.out.println(s.toString());
s.height = 8;
SingletonTest s1 = SingletonTest.getInstance();
System.out.println(s1.toString());
}
}
/*
width : 10
height : 10
width : 10
height : 8
*/
* 第四条:通过私有构造器强化不可实例化的能力
有些工具类不需要实例化,比如全是常量的类。
public class ConstantParam {
//防止实例化
private ConstantParam() {
}
public static final int MAX_TRY_TIMES = 10;
public static final String HOST = "www.jianshu.com";
}
第五条:避免创建不必要的对象
- 如果对象是不可变的,它就始终可以被重用.
下面利用static代码块重用对象
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public class Five {
private static final Date START;
private static final Date END;
static {
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.set(1900, Calendar.JANUARY, 1, 0, 0, 0);
START = cal.getTime();
cal.set(2000, Calendar.JANUARY, 1, 0, 0, 0);
END = cal.getTime();
}
/**
* 是否是20世纪
* @param date
* @return
*/
public static boolean isTwentyCentury(Date date) {
return date.compareTo(START) >= 0 &&
date.compareTo(END) < 0;
}
public static void main(String[] args) {
System.out.println(isTwentyCentury(new Date()));
Calendar c = Calendar.getInstance();
c.set(1901, Calendar.MARCH, 1, 0, 0, 0);
Date d = c.getTime();
System.out.println(isTwentyCentury(d));
}
}
/**
* false
* true
*/