前言
我很希望我10年前就能拥有这本书。有人可能认为我不需要任何Java方面的书籍,但是我需要这本书。 —— James Gosling
这几天我在回忆读过的那一本java的书籍对我影响最大,如果只能选择一本对我帮助最大的书,我觉得就是《effective java》这本书了。 很有幸能在刚毕业的时候就读到《effective java》这本书,指引我少走不少弯路弯路,每次重读都能从中获得受益。他通过简短的准则和实用建议指引我如何去写高质量,高效率的代码。下面把这些准则与君共勉,大家如需深入理解这些准则,做到从心所欲不逾矩还请购买书籍仔细品味。
创建和销毁对象
- 考虑使用静态工厂方法替代构造方法
- 当构造方法参数过多时使用builder模式
- 使用私有构造方法或枚类实现Singleton属性
- 使用私有构造方法执行非实例化
- 使用依赖注入取代硬连接资源
- 避免创建不必要的对象
- 消除过期的对象引用
- 避免使用Finalizer和Cleaner机制
- 使用try-with-resources语句替代try-finally语句
所有对象的通用方法
- 重写equals方法时遵守通用约定
- 重写equals方法时同时也要重写hashcode方法
- 始终重写 toString 方法
- 谨慎地重写 clone 方法
- 考虑实现Comparable接口
类和接口
- 使类和成员的可访问性最小化
- 在公共类中使用访问方法而不是公共属性
- 最小化可变性
- 组合优于继承
- 如果使用继承则设计,并文档说明,否则不该使用
- 接口优于抽象类
- 为后代设计接口
- 接口仅用来定义类型
- 优先使用类层次而不是标签类
- 优先考虑静态成员类
- 将源文件限制为单个顶级类
泛型
- 不要使用原始类型
- 消除非检查警告
- 列表优于数组
- 优先考虑泛型
- 优先使用泛型方法
- 使用限定通配符来增加API的灵活性
- 合理地结合泛型和可变参数
- 优先考虑类型安全的异构容器
枚举和注解
- 使用枚举类型替代整型常量
- 使用实例属性替代序数
- 使用EnumSet替代位属性
- 使用EnumMap替代序数索引
- 使用接口模拟可扩展的枚举
- 注解优于命名模式
- 始终使用Override注解
- 使用标记接口定义类型
Lambda表达式和Stream流
- lambda表达式优于匿名类
- 方法引用优于lambda表达式
- 优先使用标准的函数式接口
- 明智审慎地使用Stream
- 在流中优先使用无副作用的函数
- 优先使用Collection而不是Stream来作为方法的返回类型
- 谨慎使用流并行
方法
- 检查参数有效性
- 必要时进行防御性拷贝
- 仔细设计方法签名
- 明智而审慎地使用重载
- 明智而审慎地使用可变参数
- 返回空的数组或集合不要返回null
- 明智而审慎地返回Optional
- 为所有已公开的API元素编写文档注释
通用编程
- 最小化局部变量的作用域
- for-each循环优于传统for循环
- 熟悉并使用Java类库
- 需要精确的结果时避免使用float和double类型
- 基本类型优于装箱的基本类型
- 当有其他更合适的类型时就不用字符串
- 注意字符串连接的性能
- 通过对象的接口引用对象
- 接口优于反射
- 明智谨慎地使用本地方法
- 明智谨慎地进行优化
- 遵守普遍接受的命名约定
异常
- 仅在发生异常的条件下使用异常
- 对可恢复条件使用已检查异常,对编程错误使用运行时异常
- 避免不必要地使用检查异常
- 赞成使用标准异常
- 抛出合乎于抽象的异常
- 文档化每个方法抛出的所有异常
- 在详细信息中包含失败捕获信息
- 争取保持失败原子性
- 不要忽略异常
并发
- 同步访问共享的可变数据
- 避免过度同步
- EXECUTORS, TASKS, STREAMS 优于线程
- 优先使用并发实用程序替代wait和notify
- 线程安全文档化
- 明智谨慎地使用延迟初始化
- 不要依赖线程调度器
序列化
- 其他替代方式优于Java本身序列化
- 非常谨慎地实现SERIALIZABLE接口
- 考虑使用自定义序列化形式
- 防御性地编写READOBJECT方法
- 对于实例控制,枚举类型优于READRESOLVE
- 考虑序列化代理替代序列化实例