Effective Java 2th Part II
Effective Java 2th Part II
泛型
23、请不要在新代码中使用原生态类型
- 尽量使用泛型
24、消除非受检警告
25、列表优先于数组
- 不要混用数据与列表
- 数据是具体化的,运行时才知道类型,泛型是擦除式的,运行时会丢弃类型,在编译时强化类型
26、优先考虑泛型
27、优先考虑泛型方法
- 静态工具尤其适合泛型化
28、利用有限制通配符来提升API的灵活性
- PECS, 用于生产者使用<? extends T>, 用于消费者使用<? super T>
- 所有的comparable和comparator都是消费者
29、优先考虑类型安全的异构容器
- Map中存储不同类型的对象可以用类型对象Class
作为Key,get时候使用Class.cast进行转换
枚举和注解
30、用enum代替常量int
- 枚举是不可变的,每个枚举都有自己的命名空间,不担心重名问题
如果每个枚举对应不同的行为,使用特定于常量的方法实现
1234567public enum Oper{PLUS{double apply(double x,double y){return x+y;}},MINUS{double apply(double x,double y){return x-y;}};abstract double apply(double x,double y);}多个枚举常量同时共享相同的行为,则考虑策略枚举(枚举套枚举,里面的枚举提供方法)
1234567891011121314//伪代码public enum A{X1(B.Y1),X2(B.Y1),X3(B.Y2);enum B{Y1(void do(){}),Y2(void do(){});abstract void do();}}
31、用实例域代替序数
- 尽量不要使用ordinal方法获取序号
- 显示指定一个字段表示值
32、EnumSet代替位域
- EnumSet.of(X1,X2),表示某几个枚举值的Set
33、用EnumMap代替序数索引
- 当枚举作为Key时,使用EnumMap作为其集合载体,替代枚举数组
34、用接口模拟可伸缩的枚举
- 利用枚举实现某接口可以动态的扩展枚举,调用使用接口调用即可
- 调用端的参数两种声明方式
<T extends Enum<T> & AInterface>
和Collection<? extends AInterface>
35、注解优先于命名模式
- 使用注解而不是使用具体名称去判断执行逻辑
36、坚持使用Override注解
- 使得编译器提前得到错误
37、用标记接口定义类型
- 定义某一个类型使用接口
方法
38、检查参数的有效性
- 断言或条件判断
- 对于所有参数如果可以合理完成逻辑,限制越少越好
39、必要时进行保护性拷贝
- 对外提供的服务,要做保护性的设计
- 保护性拷贝在检查有效性之前进行
- 参数可以被不信任的子类化,勿使用clone拷贝
- 自身组件返回考虑做保护性拷贝
40、谨慎设计方法签名
- 名称谨慎
- 不过于追求便利方法
- 参数列表<=4,过多则拆分方法或创建辅助类作为参数,或者采用builder模式
- 参数优先使用接口
- boolean优先使用二值枚举setType(Person.MALE)
41、慎用重载
- 调用重载方法在编译时决定,而覆盖方法在运行时决定
- 不要导出两个具有相同参数数目的重载方法
- 构造器重载可考虑导出静态工厂
- 多个重载方法,一般将具体化的重载方法转发给通用的重载方法以保证结果的一致性
- 传递同样的参数时,所有的重载方法必须一致
42、慎用可变参数
- 每次调用均会导致一次数据分配和初始化
- 可以创建一系列接收参数数量的方法重载组,最后一个再使用可变参数1234void foo()void foo(int a1)void foo(int a1,int a2)void foo(int a1,int a2,int ...rest)
43、返回零长度的数组或者集合,而不是null
- 返回类型是数组或者集合的方法返回零长度对象
44、为所有导出的API元素编写文档注释
<pre> {@code int i=1;}<pre/>
用于导出代码{@literal Map<String,String>}
用于原样输出内容并且转移html字符