创建与销毁对象
- 考虑使用静态工厂方法(非设计模式的工厂方法)代替销毁器;
- 遇到多个构造器参数时要考虑使用构建器;
- 用私有构造器或者枚举类型强化sigleton属性;
- 通过私有构造器强化不可实例化的能力;例如:用于工具类
- 避免创建不必要的对象;例如:可将共性的东西抽出来
- 消除过期的对象引用;例如:可将数组中减少的对象进行置空
- 避免使用终结方法;
对于所有对象都通用的方法
- 覆盖equals请遵守通用约定;例如:自反性,对称性,传递性,一致性
- 覆盖equals时总要覆盖hashcode;
- 始终要覆盖toString;
- 谨慎的覆盖clone;
- 考虑实现Comparable借口;
类和接口
- 使类和成员的可访问性最小化;
- 在公有类中使用访问方法而非公有域;例如:封装
- 使可变性最小化;例如:多使用final;
- 复合优先于继承;
- 要么维继承而设计,并提供文档说明,要么就禁止继承;
- 接口优于抽象类;
- 接口只用于定义类型;
- 类层次优于标签类;
- 用函数对象表示策略;
- 优先考虑静态成员类;
泛型
- 请不要在新代码中使用原生态类型;例如:能用List<String>,不用List
使用原生态类型会在运行时导致异常,因此不要在新代码中使用。原生类型只是为了与引入泛型之前的遗留代码进行兼容和互用而提供的。让我们个快速的回顾;SetObject>是个参数化类型,表示可以包含任何对象类型的一个集合;Set<?>则是一个通配符类型,表示只能包含某种未知对象类型的一个集合:Set则是个原生态类型,它脱离了泛型系统。前两种是安全的,最后一种不安全。
- 消除非受检异常;例如:使用@SuppressWarnings("unchecked")
- 列表优先于数组;
数组和泛型有着非常不同的类型规则,数组是协变且可以具体化的;泛型是不可变的且可以被擦除的。因此,数组提供了运行时的类型安全,但是没有编译时的类型安全。反之,对于泛型也一样。一般来说,数组和泛型不能很好地混合使用如果你发现自己将它们混合起来使用,并且得到了编译时错误或者警告,你的第一反应就应该是用列表代替数组
- 优先考虑泛型;
使用泛型比使用需要在客户端代码中进行转换的类型来得更加安全,也更加容
易。在设计新类型的时候,要确保它们不需要这种转换就可以使用。这通常意味着要把类成是泛型的,只要时间允许,就把现有的类型都泛型化。这对于这些类型的新用户来说会变得更加轻松,又不会破坏现有的客户端
- 优先考虑泛型方法;例如:同第四条规则思想相同
- 利用有限制通配符来提升API的灵活性;
在API中使用通配符类型虽然比较需要技巧,但是使AP变得灵活得多,如果编
写的是将被广泛使用的类库,则一定要适当地利用通配符类型。记住基本的原则 producer-exrends. consamer-super(PECS)还要记住所有的 comparable和 comparator都是消费者
7.优先考虑类型安全的异构容器;
枚举和注解
- 用enum代替枚举常量;
- 用实例域代替序数;例如:指名枚举序号,不用自带ordinal
- 用EnumSet代替位域;
- 用EnumMap代替序数索引;
- 用接口模拟可伸缩的枚举;例如:继承
- 注解优先于命名模式;例如:@Test
- 坚持使用@Override注解;
- 用标记接口定义类型;
方法
- 检查参数的有效性;例如:校验入参
- 必要时进行保护性拷贝;例如:只是引用地址不变,内容改变
- 谨慎设计方法签名;例如:命名规范,参数合理
- 慎用重载;例如:父子类参数重载
- 慎用可变参数;
- 返回零长度的数组或者集合,而不是null;
- 为所有导出的API元素编写文档注释;
通用程序设计
- 将局部变量的作用域最小化;
- for-each优先于传统的for循环;
- 了解和使用类库;例如:Random.nextInt()与Random.nextInt(int)
- 如果要使用精确的答案,请避免使用float或double;
- 基本类型优先于装箱基本类型;例如:容易出错或影响性能;
- 如果其他类型更合适,则尽量避免使用字符串;
- 当心字符串连接的性能;例如String与StringBuilder
- 通过接口引用对象;
- 接口优先于反射机制;
- 谨慎的使用本地方法;
- 谨慎的进行优化;
- 遵守普遍接受的命名习惯;
异常
- 只针对异常的情况才使用异常;
- 对可恢复的情况使用受检异常,对编程错误使用运行时异常
- 避免不必要的使用受检的异常;
- 优先使用标准的异常;
- 抛出与抽象相对应的异常;
- 每个方法抛出的异常都要有文档;
- 在细节信息中包含能捕获失败的信息;
- 努力使失败保持原子性;
- 不要忽略异常;
并发
- 同步访问共享的可变数据;
- 避免过度同步;
- executor和task优先于线程;
- 并发工具优先于wait和notify; 例如:使用CountDownLatch
- 线程安全性的文档化;
- 慎用延迟初始化;例如:单例双重锁检查懒汉式
- 不要依赖于线程调度器;
- 避免使用线程组;
序列化
- 谨慎的使用Serializable接口;
- 考虑使用自定义的序列化形式;
- 保护性的编写readObject方法;
- 对于实例控制,枚举类型优先于readResolve;
- 考虑使用序列化代理代替序列化实例;