第 38 条:检查参数的有效性
1、公有方法,要用 Javadoc 的@throws 标签在文档中说明违反参数值限制时会抛出的异常。
/**
* 获取年龄
*
* @param age
* @return age
* @throws ArithmeticException if age < = 0
*/
public static int getAge(int age) {
if (age <= 0) {
throw new ArithmeticException("age < = 0");
}
return age;
}
2、非公有方法通常使用断言(assertion)来检查它们的参数,错误抛出 AssertionError。
// 获取姓名
private static String getName(String name){
assert name != null && name.length() != 0;
return name;
}
注:编写方法或者构造器的时候,应该考虑它的参数有哪些限制,并把这些限制通过文档注释。
第 39 条:必要时进行保护性拷贝
public final class Period {
private final Date start;
private final Date end;
public Period(Date start, Date end) {
// 可以通过 外部 Date 对象修改
// if (start.compareTo(end) > 0) {
// throw new IllegalArgumentException("start>end");
// }
// this.start = start;
// this.end = end;
// 可以通过 Period 内部 Date 对象修改
this.start = new Date(start.getTime());
this.end = new Date(end.getTime());
if (this.start.compareTo(this.end) > 0) {
throw new IllegalArgumentException("start>end");
}
}
public Date start() {
// return start;// 可以通过 Period 内部 Date 对象修改
return new Date(start.getTime());
}
public Date end() {
// return end;// 可以通过 Period 内部 Date 对象修改
return new Date(end.getTime());
}
public String toString() {
return "Period [start=" + start + ", end=" + end + "]";
}
public static void main(String[] args) {
// Date 类是可变的
Date star = new Date();
Date end = new Date();
Period p = new Period(star, end);
System.out.println(p.toString());
// end.setYear(78); // 通过 外部 Date 对象修改
p.end().setYear(78);// 通过 内部 Date 对象修改
System.out.println(p.toString());
}
}
1、对构造器的每个可变参数进行保护性拷贝。
2、保护性拷贝在检查参数的有效性之前,并且有效性检查是针对拷贝之后的对象,而不是原始对象。
3、对于参数类型可以被不可信任方子类化的参数,不要使用 clone 方法进行保护性拷贝。
第 40 条:谨慎设计方法签名
1、方法名称遵循标注命名习惯。
2、不要过于追求提供便利的方法,每个方法应该各尽其能。
3、避免过长的参数类表,四个或者更少。(分解多个方法、创建辅助类、Builder 模式)
4、对于参数类型,优先使用接口而不是类。
5、对于 boolean 参数,优先使用两个参数的枚举类型。
第 41 条:慎用重载
1、方法使用可变参数(varargs),避免重载。
2、对于多个有相同参数数目的方法,避免重载。
第 42 条:慎用可变参数
1、有时候,有必要编写 1 或者多个某种类型的方法,而不是 0 个或者多个。
2、不必改造具有 final 数组参数的每个方法,只当数量不确定的值上执行调用时才使用可变参数。
3、可变参数方法的每次调用都会导致进行一次数组分配和初始化。
第 43条:返回零长度的数组或者集合,而不是 null
第 44条:为所有导出的 API 元素编写文档注释
1、为了正确的编写 API 文档,必须在每个被导出的类、接口 、构造器、方法和域声明之前增加一个文档注释。
2、方法的文档注释应该简洁地描述出它和客户端之间的约定。