- 第一条: 使用静态工厂方法代替构造函数
这里说的静态工厂方法并不直接对应于设计模式中的工厂方法,它具有一下几个优势:
- 与构造器相比,静态工厂方法具有名称,如下所示。
class Child{ int age = 10; int weight = 30; public static Child newChild(int age, int weight) { Child child = new Child(); child.weight = weight; child.age = age; return child; } public static Child newChildWithWeight(int weight) { Child child = new Child(); child.weight = weight; return child; } public static Child newChildWithAge(int age) { Child child = new Child(); child.age = age; return child; } }
2.不必在每次调用时都创建新对象,单例模式一般都是用静态工厂方法
3.可以返回原返回类型的任何子类型对象,这也是典型的里氏替换原则,如下所示:
class Person{ public Person newInstance(){ //return new Person(); return new Zhangsan(); } } class Zhangsan extends Person{ }
- 遇到多个构造器参数时,考虑使用构建器
碰到这种多参数构造器(有必选也有可选项),很多人会使用重叠构造方法,这种方法仅适用于参数较少情况,当参数太多,并且还有不少可选参数时将难以调用,这时,Builder模式将派上用场,如下所示:
public class User { private final String firstName; // required private final String lastName; // required private final int age; // optional private final String phone; // optional private final String address; // optional private User(UserBuilder builder) { this.firstName = builder.firstName; this.lastName = builder.lastName; this.age = builder.age; this.phone = builder.phone; this.address = builder.address; } public static class UserBuilder { private final String firstName; private final String lastName; private int age; private String phone; private String address; public UserBuilder(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public UserBuilder age(int age) { this.age = age; return this; } public UserBuilder phone(String phone) { this.phone = phone; return this; } public UserBuilder address(String address) { this.address = address; return this; } public User build() { return new User(this); } } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } public int getAge() { return age; } public String getPhone() { return phone; } public String getAddress() { return address; } }
- 用私有构造方法或者枚举类型强化Sington
- 通过私有构造方法强化不可实例化的能力
- 避免创建不必要的对象
一般来说,能重用对象就应该尽可能重用,而不是每次使用时就创建新对象,如果是对象创建后不再改变的,或者本身是不可变对象,更应该如此。一个比较常见的例子是自动装箱和拆箱,如下所示:
//以下代码创建了2^31个Long对象!每次累加时都会创建一个,因此必须优先使用基本类型而不是包装类型 public static void main(String[] args){ Long sum = 0; for(long i = 0;i < Integer.MAX_VALUE; i++){ sum += i; } }
- 消除过期的对象引用
虽然jvm的GC机制已经非常强大,但在一些情况下,仍然存在内存泄漏风险,一般来说,只要类时自己管理内存(自己定义了堆栈或是缓存),就应该警惕内存泄漏的问题!
- 避免使用终结方法
终结方法通常不可预测,也很危险,它的执行时间点是不确定的,执行花费的时长也很长(大概消耗2400ns),即使要使用,也应该在finally异常块中使用。