1.检查参数有效性
这个主要是建议我们当参数有些特殊的限制时,需要检查参数的正确与否。
可被导出(public、protected)的方法
/**
* @param m the modulus,which must be positive
* @return this mod m
* @throwsArithmeticException if m is less then or equal to 0
*/
public int mod(BigInteger m){
if (m.signum() <= 0 ) {
throw new ArithmeticException("Modulus <=0 : " + m);
}
return this.n.signum() % m.signum();
}
这个是书中的一个案例,它通过调用参数的副产物m.signum()的比较是否小于等于0,来进行抛出,并且在javadoc说明文档注释中写明了@throwsArithmeticException 抛出说明。当然这个有个缺点,就是javadoc的错误抛出只能用于public(共有)与protected(受保护的)。
这里介绍一个java7中的null检查方法:Objects.requireNonNull方法。它可以返回其输入,且同时进行null检查
this.xx=Objects.requireNonNull(xx,"xx");
未能被导出(private)的方法
对于非公有方法,通常使用断言(assertion)来检查参数的
private void test(int a){
assert a!=null;
}
2.保护性拷贝
什么是保护性拷贝?
很简单,就是将对象或引用拷贝成一个新的,然后用新的对象(引用)来进行操作,避免可变出错。
例子:
/**
* 未进行保护性拷贝
* @author sardine
* */
public class TestClass {
private final Date Start;
private final Date end;
public TestClass(Date start, Date end) throws IllegalAccessException {
if(start.compareTo(end)>0){throw new IllegalAccessException("开始时间大于结束时间");}
this.Start = start;
this.end = end;
}
}
这里会导致一个问题,就是Date类本身是可变的,在判断后依然有可能造成开始时间大于结束时间;
一种解决方法是使用Instant(或LocalDateTime或ZonedDateTime)代替Date;,因为这些类是不可变的。
另一种解决方法就是使用保护性拷贝:备份对象,将其作为实例组件,而不使用原始的对象:
/**
* 保护性拷贝
* @author sardine
* */
public class TestClass {
private final Date Start;
private final Date end;
public TestClass(Date start, Date end) throws IllegalAccessException {
this.Start = new Date(start.getTime());
this.end = new Date(end.getTime());
if(start.compareTo(end)>0){throw new IllegalAccessException("开始时间大于结束时间");}
}
}
这里可以发现,它不适用原始参数start,而是通过new Date(start.getTime()),进行一个保护性拷贝来进行赋值的。