以下是我读《Effective Java》时的一些记录和总结,有什么不对的地方欢迎交流和讨论。
第一章:对象的创建和销毁
1. 考虑用静态工厂方法代替构造器:
优点:
静态工厂方法相比较于构造器, 他可以通过准确的命名来描述被返回对象的准确信息,而不是像构造器那样只能通过参数的不同来区分返回对象;
而且不会再每次调用的时候都创建一个新的实例,而是把构建好的实例缓存起来进行重复利用;
此外使用静态工厂方法还可以返回原类型的子类型,而构造器每次则只能返回构造器所属类的实例;
最后静态方法在创建参数化类型实例时代码更加的简洁,即类型推导,比如在创建泛型时只需在声明时标明使用的类型。
缺点:
当类不含公有的或者受保护的构造器,就不能被子类化,因为在子类创建实例时无法调用父类的构造器。
静态工厂方法和其他的静态方法没有任何区别,所以没有明确的进行标识,因此在查找用静态工厂方法实例化类是很困难的。
2. 遇到多个构造器参数是要考虑使用构建器:
- 构建器Builder可以很好的避免创建实例时传入参数太多的问题,可以根据需要对可选的字段进行初始化,而其他的字段则自动使用默认值。用这种方式同时也避免了使用JavaBeans模式而使得实例的初始化被分割开的状况,使得类的实例化更加的安全可靠。此外Builder模式也使得代码易于阅读。
3. 通过私有构造器或者使用枚举类型来强化Singleton属性:
- 私有化构造器是实现单例模式的必要步骤,通过私有化构造器使得外部无法通过构造器直接创建一个实例,而是通过提供的公共方法获取唯一的实例,但是要考虑到线程同步的问题,序列化 和反序列化等问题;或者是使用枚举来保证实例的唯一性,使用枚举的特性可以很好的保证实例的唯一性,同时枚举也自动的实现了线程安全,序列化和反序列化等问题,但是枚举的使用要消耗更多的资源。
4. 通过私有化构造器来强化不可实例化的能力:
- 此条和第三条的区别在于第三条是主动的希望只能维持一个唯一的实例对象,并且保持线程安全和序列化反序列化安全,而此条则是完全不希望该类有任何的实例化对象,比如我们常使用的工具类(绝大部分是提供静态方法)完全没有实例化的必要,但是我们若不做任何的处理,系统会默认的提供一个无参数的构造器,这就使得该类有可能被实例化。因此我们应该主动提供私有的构造器来加强不可实例化的能力。
5. 避免创建不必要的对象:
- 创建对象始终会消耗系统一定的资源,所以要尽可能的避免创建不必要的对象。例如:String s = new String(“test”)—–(每次执行到该语句时都会创建一个新的String实例,严重的消耗了资源),但是如果改成String s = “test”的话,则每次执行到该语句时都会重新使用第一次创建的实例。
6. 消除过期的对象引用:
- 当一个对象确定不再会被引用到时要注意对其所占用内存的释放(虽然Java中不能手动释放内存,但是要解除对该对象的引用),否则gc将不会对改对象所占用的内存进行回收,易造成内存泄漏。通常可以缩小变量的作用域范围,使其在使用完毕之后自动结束其生命周期为最好,其次也可以在明确不会再使用该变量时手动进行消除。
7. 避免使用终结方法:
- 使用终结方法会导致性能不稳定,而且很损耗性能,降低可移植性。例如当需要一个循环线程结束时不是直接调用其stop()方法,而是修改器run()方法中循环的条件,通过设置结束的标志来使得线程平稳的结束运行,同时也记录下了改实例当前的运行状况。