创建和销毁对象
- 考虑用静态工厂方法代替构造器
- 遇到多个构造器参数时,要考虑用构建器
注:在lombok插件中 有个@Builder
注解 可以方便生成构建器,建造者模式 - 用私有构造器或者枚举类型强化Singleton属性
注:可以参考单例的几种实现方式,推荐枚举 和 静态类的方法实现,避免饿汉式加载和懒汉式的线程同步问题 - 通过私有构造器强化不可实例化的能力。
注:对于一些工具类 建议加上私有构造器 避免无意义的实例化。 - 避免创建不必要的对象
- 消除过期的对象引用
注:常见的导致内存泄漏的情况,a.栈的设计,出栈时未将当前栈位置空。b.缓存,c.监听器的或其他回调,只注册 不取消,可以尝试使用软引用 或者弱引用。 - 避免使用终结方法
对所有对象都通用的方法
- 覆盖equals时请遵守通用约定
注:自反性x.equals(x) == true
、对称性、传递性、一致性 - 覆盖equals时总要覆盖hashCode
注:equals相等,hashCode必须相等;但是hashCode相等,equals不一定相等 - 始终要覆盖toString方法
注:为了输出打印对象的可读性,务必覆盖toString对象 - 谨慎底覆盖clone
注:注意深拷贝和浅拷贝 - 考虑实现Comparable接口
类和接口
- 使类和成员的可访问性最小化
注:类的几种访问级别 - 在公有类中使用访问方法而非公有域
- 使可变性最小化
注:不可变对象尽量用final修饰 包括不可变属性字段,本质上实现线程安全 - 复合优先于继承
注:封装类 ,转发类,装饰模式的应用 - 要么为继承而设计,并提供文档说明,要么就禁止继承
- 接口由于抽象类
注:多重组合继承,通用的骨架实现类 如:AbstractSet
等 - 接口只用于定义类型
注:接口导出常量属于反面例子,以后避免使用,可以使用工具类替代 - 类层次由于标签类
- 用函数对象表示策略
- 优先考虑静态成员类
泛型
- 请不要在新代码中使用原生态类型
- 消除非受检警告
- 列表优先于数组
- 优先考虑泛型
- 优先考虑泛型方法
- 利用有限通配符来提升API的灵活性
- 优先考虑类型安全的异构容器
枚举和注解
- 用enum代替int常量
- 用实例域代替序数
- 用EnumSet代替位域
- 用EnumMap代理序数索引
- 用接口模拟可伸缩的接口
注:这个实现很妙,可以多参考借鉴 - 注解优于命名模式
注:命名模式早已淘汰 - 坚持使用Overrider注解
- 用标记接口定义类型
方法
- 检查参数的有效性
注:assert
断言会抛出 AssertionError 异常,为Error的子类。公有方法一般不用assert
校验 - 必要时进行拷贝性保护
注:各层之间对象转换 DTO,DOMAIN,DO,VO等,各域之间对象相互拷贝 - 谨慎设计方法签名
- 慎用重载
- 慎用可变参数
- 返回零长度的数组或者集合,而不是null
- 为所有导出的API元素编写文档注释
通用程序设计
- 将局部变量的作用域最小化
- for-each循环优先于传统的for循环
- 了解和使用类库
- 如果需要精确的答案,请避免使用float和double
- 基本类型优先于装箱基本类型
- 如果其他类型更合适,则尽量避免使用字符串
- 当心字符串链接的性能
- 通过接口引用对象
- 接口优先于反射机制
- 谨慎地使用本地方法
- 谨慎地进行优化
- 准守普遍接受的命名惯例
异常
- 只针对异常的情况才使用异常
- 对可恢复的情况使用受检异常,对变成错误使用运行时异常
- 避免不必要地使用受检的异常
- 优先使用标准的异常
注:常见的标准异常有
IllegalArgumentExcetion
: 参数非法
IllegalStateException
: 状态非法
NullPointerExeption
禁止使用null的情况下 参数为null
ConcurrentModificationException
并发修改异常
UnsupportedOperationException
不支持请求操作 - 抛出与抽象相对应的异常
- 每个方法抛出的异常都要有文档
- 在细节消息中包含能捕获失败的信息
- 努力是失败保持原子性
- 不要忽略异常
并发
- 同步访问共享的可变数据
- 避免过度同步
- executor和task 优先于线程
- 并发工具优先于wait和notify
- 线程安全性的文档化
- 慎用延迟初始化
- 不要依赖于线程调度器
注:尽量确保可运行的线程数量不明显多于CPU核数,否则资源竞争将严重降低性能 - 避免使用线程组
序列化
- 谨慎的实现Serializable接口
- 考虑使用自定义的序列化形式
- 保护性的编写readObject方法
- 对于实例控制,枚举类型优先于readResolve
- 考虑用序列化代理替代序列化实例