静态工厂方法代替构造器
优点
- 包含名称易于阅读
- 避免创建不必要的重复对象
- 可以返回原返回类型的子类型,类型更加灵活
- 创建参数化类型实例代码更简洁
缺点
- 静态方法所在类没有public或者protected的构造器无法子类化
- 实际上和其他静态方法没有区别
多个构造器参数考虑构建器
- 静态工厂和构造器不能很好地扩展到大量的可选参数
- 重叠构造器模式可行参数多时,难写且阅读困难
- 构造JavaBean过程中可能处于不一致状态
- JavaBean模式阻止把类做成不可变的可能,需要额外确保线程安全
- Builder模式,既有JavaBean良好的可读性,又有重叠构造器的安全性
- 适用场景:静态方法或构造器参数较多,特别是可选参数多
- 劣势:ORM框架依赖java bean的set和get方法
用私有构造器或枚举类型强化单例属性
私有构造器
- 通过反射机制调用私有构造器攻击
setAccessible(true)
,在修改构造器创建第二个实例时抛异常 - 反序列化会生成新的实例,提供readResolve方法返回原有实例
单元素枚举类型
- 反射与反序列化时防止多次实例化
避免使用终结方法
- 终结方法不能保证及时执行,不能保证会被执行
- 非常严重的性能损失
终止对象中封装的资源应提供显式终止方法
1
inputstream/outputstream/connection的close方法 或Timer的cancel方法
终结方法好处
- 忘记调用显式方法时可充当“安全网”
- 终结对象的本地对等体,终止非关键的本地资源
私有构造器强化不可实例化
只包含静态方法和静态域的类,工具类不具有任何实例化意义
该类组织起来的两种特性
基本类型的值或者数组类型上的相关方法组织起来
1
java.lang.Math/java.util.Arrays
实现特定接口的对象上的静态方法(包括工厂方法)组织起来.
1
java.util.Collections
避免创建不必要的对象
- 当心无意识的自动装箱
- 适配器:把功能委托给后备对象,为后备对象提供一个可替代接口,它没有其他状态信息,不需要多个实例
重用不可变对象
- 字符串字面常量
- 静态工厂方法优先.
1
Boolean.valueOf(String)
重用已知不会被修改的可变对象
Calendar
实例的创建代价特别昂贵- 延迟初始化
lazily initializing
,但是方法实现更加复杂,难以提高性能
- 维护轻量级线程池避免重复创建对象不是好做法。原因:维护代码跟高度优化的现代JVM垃圾回收相比性能太差
- “保护性拷贝”如果重用现有对象会导致潜在错误或安全漏洞,最好创建新的对象
小对象创建回收在现代jvm上非常廉价。通过创建附加对象,提升程序清晰性、简洁性和功能性,通常是个好事。不必要的对象只会影响程序风格和性能。
消除过期对象引用(内存泄漏)
- 一单对象引用已经过期需要清空这些引用,即赋值为
null
- 清空应该是一种例外而不是规范行为。通过紧凑的作用域范围定义变量,结束生命周期后自然会清空。
- 内存泄漏常见来源是缓存。定时清除或在加入新缓存时清除。
- 后台线程
Timer
或ScheduledThreadPoolExecutor
完成定时清除 LinkedHashMap
的removeEldestEntry
方法添加时清除最旧的条目。- 复杂缓存必须直接使用
java.lang.ref
- 后台线程
- 监听器和其他回调也是内存泄漏常见来源,只保存回调、监听器的弱引用。比如保存成
WeakHashMap
的键 - 通过仔细的代码检查或
Heap
剖析工具能发现内存泄漏问题