《Effictive Java 二》

继续阅读:《Effictive Java 阅读笔记一》

四、泛型

Item19. 对于要写类名的地方,就不要写原生类型

例如:一个string list,要写成List,而不是List或者List,这样可以避免加错元素。如果确定真的想用,用Object吧或者List< ? >也成。

Item20. 消除非受检警告

unchecked warning,可以加一个@SuppressWarning("unchecked"),这个有范围大小,一般不建议放在方法上,范围越小越好。

Item21. 列表优先于数组

数组加元素在运行时才出问题,而列表会在编译时就告诉你有类型相关的问题。

Item22. 尝试自己写泛型类和方法

例如将Object改为泛型。里面遇到编译问题,考虑一下消除非受检警告。

五、枚举

Item23 能用枚举就不要用整数来表示

Item24 如果枚举需要用于实现一个对应关系,可以使用实例域,例如给每一个枚举加一个数字。

也就是我之前常用的加一个int,这样枚举类型就和序号是分开的了,另外也还可以加String等任何你觉得需要附加到枚举上面的字段。

Item25 使用EnumSet来取代用位操作表多个枚举集合

我们可以通过item24把每一个枚举用2,4,8等位来表示,这样通过|操作判断就知道包含了哪几个枚举类型。但是这样做还是不太好,使用EnumSet是更好的方法。在数量上也没有约束。

Item26 使用EnumMap来取代序号索引

Item27 使用接口来模拟可伸缩的枚举

具体的操作:

public interface Operation {double apply(double x, double y);}

public enum BasicOperation implements Operation {
PLUS("+") {public double apply(double x, double y) { return x + y; }},
MINUS("-") {public double apply(double x, double y) { return x - y; }},
TIMES("*") {public double apply(double x, double y) { return x * y; }},
DIVIDE("/") {public double apply(double x, double y) { return x / y; }};

private final String symbol;
BasicOperation(String symbol) { this.symbol = symbol;}
@Override public String toString() {return symbol;}

}

而扩展的可以为operation再加一个枚举类型 public enum ExtendedOperation implements Operation {
EXP("^") {public double apply(double x, double y) {return Math.pow(x, y);}},

private final String symbol;
BasicOperation(String symbol) { this.symbol = symbol;}
@Override public String toString() {return symbol;} }

这样,在遍历的时候还是可以获取到全部的类型: private static & Operation> void test(
Class opSet, double x, double y) {
for (Operation op : opSet.getEnumConstants()) System.out.printf("%f %s %f = %f%n",x, op, y, op.apply(x, y)); }

六、方法

Item28 检查方法传入参数的合法性

1. 对于公有方法,需要使用javadoc的@throws来抛出异常
2. 对于私有方法,建议是加断言,但我更喜欢在逻辑上考虑清楚
3. 对参数的限制越少越好
4. 记得写好文档

Item29 保护好传入的对象,因为传的是引用,所以必要时拷贝一类而不要直接使用传入的参数对象

需要想到使用的参数未来很可能会被修改
如果有性能方面的考虑,那么需要在文档中说明

Item30 方法名是需要设计的

可以参考javaApi.
每个方法都要竭尽所能,过多的方法会导致类难以学习使用文档化测试和维护,只有一个方法需要经常被使用到,才单独提出来
避免过长的参数列表,最好是四个以下,越少越好。缩短的方法可以是分解为多个,但是会导致上面方法过多的问题。另一种缩短的方法是使用辅助类,把这些参数合并起来。
对于参数类型,最好使用接口而不是类。
对于boolean,最好使用有两个类型的枚举,这样便于阅读和维护,也更加便于后续的扩展

Item31 慎用重载

调用哪个方法,是由编译器决定的。

Item32 慎用可变参数

Item33 为所有要导出的接口编写文档

注意一下文档的格式,例如使用html标签,或者使用{@code}标签来增强可读性。同一个类或者接口的两个成员或者函数,不要使用同样的概要描述。

七、编程习惯

Item34 使局部变量最小化

最好的办法就是在使用的地方声明。如果还不能初始化,就在可以初始化的时候再声明。另外还可以将方法抽取出来,使得每一个方法都比较小。

Item35 forEach循环比普通for循环好

有几种使用forEach有点麻烦:删除某个元素;修改;需要多次迭代

Item36 需要对类库熟悉

好处:类库的性能会越来越好,错误越来越少,因为大家都在用;更易读;

Item37 精确计算请用BigDecimal

Item38 除非要放在集合中,否则基本类型优先于装箱后的

Item39 如果有更好的类型,请不要使用String

Item40 能不使用反射就别用反射

Item41 能不使用本地方法就别用本地方法

Item42 不要做优化,除非有好的性能测试方法了

Item43 使用通用的命名方法

八、异常

Item44 别在不需要的时候使用异常

原因:jvm很少优化异常处理性能;可能阻止别的特定优化;

Item45 尽可能使用标准的异常

Item46 抛出与方法相对应level的异常

Item47 抛出的异常记得写在文档中

Item48 在抛出的异常中加入必要的失败的信息

Item49 在异常情况下尽量保持原子性

Item50 别漏写异常,也别泛写异常

虽然我自己经验用泛写Exception来避免漏写。。。

九、并行

Item51 同步访问共享的可变数据

该加synchronized或者atomic的就加了吧

Item52 避免过度同步

例如StringBuffer.如果自己不确定,就需要在文档中表明非线程安全。在同步区域内做尽可能少的操作。使用并发集合类是一种比自己手写更靠谱的方式。

Item53 优先考虑Exexutor Framework

Item54 Exexutor Framework、Concurrent Collection、Synchronizer这样的工具优先于手写wait和notify

Item55 写线程安全时,注意一下延迟初始化

想一下单例的那个面试题

十、序列化

不要做序列化的事
comments powered by Disqus