1 代码应该被重用 ,而不是被拷贝。
2 错误应该尽早被检测出来,最好是在编译时刻。
3 接口、类、数组是引用类型(对象), 基本类型不是
第二章 创建和销毁对象
1 考虑用静态工厂方法代替构造器。
优势:
1 有名称(多个 相同签名 的构造器)
2 不必每次调用它们都创建一个新对象。(可控)
3 可以返回原返回类型的任何子类型的对象。(灵活,可返回一个接口类型,强迫客户端面向接口编程)
4 静态工厂方法可以利用 类型推导 简化 参数化类型实例 的创建。
缺点:
1 类不含public protected的构造器,不能被子类化。
2 Javadoc API 文档中,没有特殊标明 静态工厂方法。 不方便查阅。
一些惯用名称:
1. valueOf,实际上是类型转换方法
2. of,valueOf的简洁替代。
3. getInstance。
4. newInstance。与3相比,确保返回的每个实例都与其他的所有实例不同。
5. getXXXX。
6. newXXXX。
总结:
和构造器比,各有好处。优先使用静态工厂。
(重用对象的好处 可以用 == 替代 equals,性能更好。静态工厂参考Boolean.valueOf().)
2 遇到多个构造器参数时,要考虑用Builder
静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数。
Builder模式,既能保证像重叠构造器模式那样的安全性,也能保证像JavaBeans模式那么好的可读性。还可以有多个 可变参数。
Builder模式构建时,被构建类的field一般都是final。
如类的构造器或者静态工厂中具有多个参数,特别大多数参数时可选的时候,使用Builder模式。
(最好一开始就用Builder,否则兼容以前的构造函数和静态工厂很烦。)
3 用私有构造器或者枚举类型强化Singleton属性
public enum EnumSingleton {
INSTANCE;
EnumSingleton() {
System.out.println(“我被创建了”);
}
public void metho1() {
System.out.println(“单例的方法”);
}
}
4 通过私有构造器强化不可实例化的能力
副作用是 使得一个类不能被子类化。可用作常量定义工具类。
5 避免创建不必要的对象
Map的keySet 每次返回的是同一个Set实例。
优先使用基本类型而不是装箱基本类型,当心无意识的自动装箱。
并不代表我们要尽可能的避免创建对象,对于小对象而言,它的创建和回收动作是非常廉价的。
反之,通过维护自己的对象池来避免创建对象并不是一种好的做法。
除非池中的对象是非常重量级的。
6 消除过期的对象引用
避免内存泄漏。
只要类是自己管理内存(数组存储对象引用,及时置位null),程序员就应该警惕内存泄漏问题。
7 避免使用终结方法
终结方法finalizer通常是不可预测的,也是很危险的,一般情况下是不必要的。
它不保证何时执行,是否执行。且会带来性能损失。
如果需要,提供一个显式的终止方法。类似InputStream。
显式的终止方法通常与try-finally结合起来使用,以确保及时终止。在finally子句内调用显式的终止方法,可以保证即使在使用对象的时候,有异常抛出,该终止方法也会执行。
终结方法的合法用途:
1 使用者忘记调用显式终止方法,终结方法可以充当 “安全网”,迟一点释放比不释放要好。(希望尽可能不要这样) 。如果终结方法发现资源还未被终止,应该在日志中记录一条警告。因为这是客户端的一个bug。但是要考虑这种额外的保护是否值得。
四个示例:FileInputStream、FileOutputStream、Timer、Connection。
2 释放native对象的资源。
还有一点,终结方法链不会自动执行。如果类有终结方法,并且子类覆盖了终结方法,要手动调用超类的终结方法。应该在try中终结子类,在finally中调用超类的finalize().
protected void finalize() throws Throwable {
try {
//finalize自己
} finally {
super.finalize();
}
}
为了防范子类没有手工调用超类的终结方法。可以采用匿名内部类实现一个终结方法守卫者。
//终结方法守卫者
private final Object finalizerGuardian = new Object() {
@Override
protected void finalize() throws Throwable {
//在这里调用外围实例的finalize
FinalizeTest.this.finalize();
}
};
第三章 对于所有对象都通用的方法
8 覆盖equals时请遵守通用约定
“值类(value class)”仅仅是一个表示值的类,例如Integer或Date。需要覆盖equals()。
有一种值类不需要覆盖,即第一条确保下的“每个值至多只存在一个对象”的类。枚举类型就属于这种类。
equals()方法实现了等价关系。
-
<