清晰性和简洁性最重要
模块尽可能小
重用代码
模块间依赖性尽可能小
错误尽早被检测出来
二.创建和销毁对象
1.考虑用静态工厂方法代替构造器(服务提供者框架)
2.遇到多个构造参数时考虑用构造器(建造者模式)
3.用私有构造器或者枚举类型强化单例属性
4.通过私有构造器强化不可实例化能力
5.避免创建不必要的对象(优先使用基本类型,当心无意识的自动装箱)
6.消除过期对象的引用(类是自己管理内存时,要小心。2.缓存3.监听器和回调)
7.避免使用终结方法(显示关闭)
三.对于所有对象都通用的方法
8.覆盖equals时请遵守通用约定(等价关系:自反性,对称性,传递性,一致性)
(高质量equals诀窍:1.使用==检查参数是否为这个对象的引用
2.用instanceof检查参数是否为正确的类型
3.把参数转换为正确的类型
4.对于该类的每个“关键”域检查参数中的域是否和对象对应的域相匹配
5.问自己3个问题,是否对称,传递,一致
不要将object对象替换为其他类型)
9.覆盖equals时总要覆盖hashcode
10.始终要覆盖toString()
11.谨慎地覆盖clone(clone()就是另一个构造器,必须确保它不会伤害到原始对象并正确地创建被克隆对象中的约束)
12.考虑实现comparable接口
四.类和接口
13.使类和成员的可访问性最小化(实例域决不能是公有的)
14.在公有类中使用访问方法而非公有域
15.使可变性最小化
(不可变类规则:1.不提供任何会修改对象状态的方法
2.保证类不会被扩展
3.使所有的域都是final
4.使所有的域都成为私有
5.确保对任何可变组件的互斥访问)
16.复合优先于继承
17.要么为继承而设计,并提供文档说明要么禁止继承(构造器决不能调用可被覆盖的方法)
18.接口优于抽象类
19.接口只用于定义类型
20.类层次优于标签类
21.用函数对象表示策略
22.优先考虑静态成员类(如果声明成员类不要求访问外围实例,就要使它成为静态成员类)
五.泛型
23.请不要在新代码中使用原生态类型
24.消除非受检警告
25.列表优先于数组
26.优先考虑泛型(只要时间允许,就把现有的类型都泛型化)
27.优先考虑泛型方法(静态工具方法尤其适合泛型化)
28.利用有限制通配符来提升api的灵活性(PECS:生产者继承,消费者-super
不要用通配符类型作为返回类型,所有的comparable..comparator都是消费者)
29.优先考虑类型安全的异构容器
六.枚举和注解
30.用enum代替int常量
31.用实例域代替序数
32.用EnumSet代替位域
33.用EnumMap代替序数索引
34.用接口模拟可伸缩的枚举
35.注解优先于命名模式
36.坚持使用Override注解
37.用标记接口定义类型
七.方法
38.检查参数的有效性
39.必要时进行保护性拷贝(对于参数类型可以被不可信任方子类化的参数,请不要用clone方法进行保护性拷贝;只要有可能尽量用不可变对象作为组件)
40.谨慎设计方法签名(谨慎地选择方法的名称,不要过于追求提供便利的方法,避免过长的参数列表;
缩短参数长度方法:1.把方法分解成多个方法
2.创建辅助类3.建造者模式;boolean参数,要优先使用两个元素的枚举类型)
41.慎用重载(重载方法选择是静态的,覆盖方法选择是动态的,保守策略:永远不要导出两个具有相同参数数目的重载方法,对可变参数不要重载)
42.慎用可变参数
43.返回零长度的数组或集合,而不是null
44.为所有导出的API元素编写文档注释(熟悉文档注释规范;应说明方法做了什么,前提,后置条件,副作用,线程安全性,可序列性;方法和构造器概要描述:动词短语,类和接口:名词短语;)
八.通用程序设计
45.将局部变量的作用域最小化(第一次使用它的地方声明,包含初始化表达式;使方法小而集中)
46.foreach优于传统的for循环(可遍历任何实现iterable接口的对象;无法使用的情况,过滤,转换,平行迭代)
47.了解和使用类库(lang.util.io.concurrent.collections) 要多了解
不要重复发明轮子
48.如果需要精确的答案,请避免使用float,double(正确的办法是使用bigdecimal,int,long进行货币计算;如果数值可能超过18位数字必须使用bigdecimal)
49.基本类型优于装箱基本类型(集合中的键值,参数化类型时只能用包装类型)
50.如果其他类型更合适,则尽量避免使用字符串
51.当心字符串连接的性能(stringbuilder)
52.通过接口引用对象(或类层次结构的基类,因为更灵活)
53.接口优于反射机制(仅仅使用反射机制实例化对象,访问对象则使用编译时已知的某个接口或者超类)
54.谨慎地使用本地方法(不安全)
55.谨慎地进行优化(努力编写好的程序,在设计时对api,线路层协议,数据结构考虑性能问题。 好性能自然会来)
56.遵守普遍接受的命名惯例
九.异常
57.只针对异常情况才使用异常
58.对可恢复的情况使用受检异常,对编程错误使用运行时异常
59.避免不必要地使用受检的异常
60.优先使用标准的异常
61.抛出与抽象相对应的异常(异常转译:更高层的实现应该捕获低层的异常,同时可以抛出按高层抽象进行解释的异常;异常链)
62.每个方法抛出的异常都要有文档
63.在细节消息中包含能捕获失败的信息(细节消息应该包含有贡献的参数和域)
64.努力使失败保持原子性(在执行操作之前检查参数的有效性;使任何可能失败的计算部分都在对象状态修改之前发生;编写一段恢复代码;在对象的一份临时拷贝上执行操作,再写回)
65.不要忽略异常
十.并发
66.同步访问共享的可变数据(将可变数据限制在单个线程中;安全发布;共享可变数据需要同步)
67.避免过度同步(不要从同步区域调用外来方法;尽量限制同步区域内部的工作量)
68.executor和task优先于线程
69.并发工具优先于wait,notify(对于间歇式定时,始终应该优先使用namoTime)
70.线程安全性的文档化
71.慎用延迟初始化
72.不要依赖于线程调度器(线程不应该一直处于忙-等)
73.避免使用线程组
十一.序列化
74.谨慎地实现Serializable接口(为继承设计的类和用户的接口尽可能地少继承Serializable接口;内部类不应该实现。。。接口,静态成员类可以)
75.考虑使用自定义的序列化形式(一个对象的物理表示法等同于它的逻辑内容,可能就适合使用默认序列化形式;编写一个显式的序列化uid)
76.保护性地编写readObject方法
77.对于实例控制,枚举类型优先于readResolve
78.考虑用序列化代理代替序列化实例