1. 用静态方法替代构造器(五个优点、两个缺点)。
相比于构造器,优点如下:
- 有名称;
- 不用再每次调用时返回一个新的对象;
- 可以返回声明类型的子类型的对象;适用于基于接口的框架;
- 每次调用时,可以基于不同的参数返回不同的对象实例;
- 所返回对象的类并不一定要存在;这种灵活的静态工厂方法提供了灵活的服务提供者框架;
相比于构造器,缺点如下: - 如果没有公共的或者受保护的构造器,就不能为其生成子类;
子类构造器会自动调用父类构造器,所以当父类没有构造器为其调用时,就没有办法创建子类;
- JavaDoc生成文档时,对其展示没有构造器明显;
2. 当构造函数的参数比较多时使用生成器。
- Builder类作为使用类的静态内部类,其字段为外部类可能需要的构造参数;
- 可以防止复杂对象在构造过程中被破坏;
- 同一个生成器可以用来生成多个相同的对象(享元);
3. 利用私有构造器或者枚举类型强化Singleton属性;
public class Elvis {
public static final Elvis INSTANCE = new Elvis();
private Elvis() {...}
// ...
// 第二种
private static final Elvis INSTANCE = new Elvis();
public static Elvis getInstance () { return INSTANCE; }
// 此处的作用:防止Singleton的对象序列化后,再反序列化会生成新的对象,
// 破坏了Singleton的设计;
private Object readResolve() {
return INSTANCE; // 让GC处理假的Elvis对象;
}
}
4. 利用私有构造器防止类被实例化;(上面👆的代码有示例)
5. 优先考虑通过依赖注入来链接资源;
对于行为会被底层资源以参数化的方式影响的类而言,静态工具类和Singleton类都不合适;
// 依赖注入:即将依赖资源通过参数的形式传递到类的构造器中
public class SpellChecker {
private final Lexicon dictionary;
public SpellChecker(Lexicon dictionary) {
this.dictionary = Object.requiredNonNull(dictionary);
}
}
6. 避免创建不必要的对象;
- 比如正则处理会生成Pattern对象,对性能要求高的场景,可以预先生成Pattern对象;
- 自动装箱也会生成可能不必要的对象;所以优先使用基本类型而不是其封装类,并提防无意中的自动装箱;
7. 及时清理掉过期的引用;
8. 承接上一点,避免使用终结(finalizer)方法和清理(cleaner)方法;
- 两个方法清理不够及时,甚至不保证会运行;
- 终结过程中发生的异常会被忽略,导致其他对象可能处于损坏状态;
9. 与try-finally相比,首选try-with-resources;
10. 重写equals方法;
需要遵守五个约定:
-
自反性
:x.equals(x); -
对称性
:x.equals(y) 与 y.equals(x)结果相同; -
传递性
:x.equals(y) && y.equals(z) => x.equals(z); -
一致性
: 无论何时调用,x.equals(y)的结果不变; -
非空性
:x.equlas(null) 返回false;
编写高质量equals方法的技巧: - 使用
==
检查参数是否指向当前对象的引用; - 使用 instanceof 运算符检查参数是否具有正确的类型;
- 将参数转换为正确的类型;
- 对于类中每个“重要”的字段,检查参数的这些字段是否与当前对象相应字段匹配;
11. 重写equals方法时应始终重写hashcode方法;
- equals相等,hashcode一定相等;
- hashcode相等,equals不一定相等;
- hash算法应尽可能返回分散的散列值,以避免hash冲突,导致检索性能较低;
12. 总是重写toString() 方法;
- 可以增强debug或者日志中类的可读性;
13. 谨慎重写clone方法;
- clone的实现可能会是一个浅拷贝;
- clone充当了构造器的作用,必须确保它不会对原始对象造成伤害,并确保它在克隆体上正确建立不变式;
- 大多数情况,提供复制构造器会是更好的选择;
public class Yum {
public Yum(Yum yum) {
// ...
}
}
14. 考虑实现Comparable接口;
- 当类可能需要一些比较操作时可考虑实现;
- 尽量使用系统提供的基于静态的比较器,或者基于比较器构造方法的比较器;
// 基于静态的比较器
static Comparator<Object> hashCodeOrder = new Comparator<>() {
public int compare(Object o1, Object o2) {
return Integer.compare(o1.hashCode(), o2.hashCode());
}
}
// 基于比较器构造方法
static Comparator<Object> hashCodeOrder = Comparator.compareInt(o -> o.hashCode());