学习目的:
- 何时以及如何创建对象
- 何时以及如何避免创建对象
- 如何确保对象适时销毁
- 如何管理对象销毁前必须进行的各种清理动作
1. 考虑用静态工厂方法代替构造器
该静态工厂方法不同于设计模式中的工厂方法,主要用于如何鲜明提供可定制化的实例构造方法。
优势:
1. 静态方法可以提供名称,可以确切地描述返回的对象,更易于代码阅读、理解。
2. 不必每次调用的时候都创建新的对象,这样就可以反复使用预先构建好的对象,或者将创建的对象缓存起来,有利于提升性能,这种方式在单例模式中应用较多。
3. 通过依赖于接口,而不依赖与具体实现,可以灵活返回实现该接口的子类。
4. 构造参数化实例时,代码更加简洁。
劣势:
要提供可在外部实例化的类,否则优势3无法体现,而已静态工厂方法依然只是一个普通的静态方法,需要提供注释来表示她的构造功能说明。
针对劣势方面,可以提供通用的方法名称如valueOf,newInstance,getInstance等来标示该方法的存在意义。更主要的是在构建对象时考虑需不需要通过静态工厂来灵活构造实例对象。
2. 遇到多个构造器参数时要考虑用Builder
在实例化某些对象时,可能需要提供多个参数,而有些参数是必须的或可选的,这个时候一般就会提供多个构造器来实例化不同的对象。
- 对象的实例化参数增多,意味着构造方法也同时增多,代码的可读性也随之下降。
- 采取builder模式,完全由Builder来灵活定制对象的实例属性,针对每个属性提供一个set方法即可。
- 调用build方法来构建对象,并在对象构建方法中即可一次性检测参数设置异常
3. 用私有构造器或枚举来强化Singleton模式
- 对于实现Singleton模式一般都需要将构造器私有化,但通过Java的反射方式依然能破坏该模式,可以通过修改私有构造器在实例化第二个对象时直接抛出异常来保证单例不被破坏。
- 对象的序列化和反序列号也能破坏单例模式,需要提供readResolve方法来保证返回实例相同。
- 单元素枚举方式来保证Singleton模式,自动提供上述两种功能,并且能保证线程安全,是目前Singleton最佳方法。
4. 通过私有构造器来强化不可实例化的能力
有时候需要编写一个只需要包含静态方法或静态域的类,用于提供一些工具性的方法,而这样的工具类一般不希望被实例化。
在编写类时若不提供构造方法,则系统会自动生成一个无参构造器,所以我们需要编写一个私有构造器,并在内部直接抛出异常,你也可以在上面编写注释表明意图。
5. 避免创建不必要的对象
what:
不必要的对象的鲜明特征就是对于反复使用的某一功能或方法,在每次运行时都会重新创建对象,而不是使用之前已有对象。
why:
对象的创建是需要代价的,大量创建无用对象既增加占用内存也减少了代码运行流畅,比如创建数据库连接对象需要较大开销,如果能复用之前已有连接对象,对于提升性能具有显著帮助。
how:
可以考虑在将常用对象缓存住,比如静态域等等。但是不要总是考虑缓存对象这样不一定能提升能力,只是对于一些创建对象开销较大并且使用较多对象缓存,创建一些微对象对于代码运行并没有多少影响。
6. 消除过期的对象引用
Java是能够自动进行垃圾回收但前提是对象没有被引用,而在代码编写过程中由于缓存或一些其他使用导致在不需要该对象时,依然内部持有该对象的引用,导致该对象没有被及时释放,从而导致内存泄漏。所以对不再需要使用的对象尽量置为null或者对于一些对象采用弱引用。
7. 避免使用终结方法
首先终结方法是JVM自己调用的,而随着垃圾回收算法改变,终结算法调用时刻也是不一致的,所以不要依赖终结方法做一些额外的操作,这样会导致整个应用崩溃的,而且Java并不提供能直接命令系统进行垃圾回收的方法,System.gc()也只是建议开始系统回收的。
如果显示覆盖终结方法,来一定要调用父类终结方法,因为JVM不会主动调用父类的gc方法的。