《Effective Java读书笔记》--方法

检查参数的有效性

方法在执行前,首先对参数进行检查,若是参数不合法,应该清楚地以一个适当的异常指明错误的缘由。
对于非公有方法,调用者应该保证传入的参数是合理的,因此应该以assert断言参数的有效性。
但“检查参数的有效性”这条规则也有例外,好比检查工做十分昂贵,或者不切实际,而且在计算过程当中有效性检查工做也被隐含完成时。

须要时使用保护性拷贝

public class Period {
	private final Date start;
	private final Date end;

	public Period(Date start, Date end) {
		// if (start.compareTo(end) > 0) { //不是线程安全的
		// throw new IllegalArgumentException();
		// }
		//
		// this.start = start;
		// this.end = end;

		this.start = new Date(start.getTime()); // 保护性拷贝是在检查参数有效性以前进行。
		this.end = new Date(end.getTime());

		if (this.start.compareTo(this.end) > 0) {
			throw new IllegalArgumentException();
		}
	}

	public Date start() {
		// return this.start;
		return (Date) this.start.clone();
	}

	public Date end() {
		// return this.end;
		return (Date) this.end.clone();
	}
}

Period中被注释掉的代码,没有采用保护性的拷贝。这样的话,Period保存的是两个引用,start和end返回的也是引用,那么用户能够经过引用改变Period的状态,致使start>end非法状况出现。 java

注意到Period的构造方法中,保护性拷贝是在检查参数有效性以前进行,为何呢? 数组

这是为了线程安全考虑。假如线程A恰好执行完参数有效性检查,OK了,而后紧接的执行线程B,线程B改变了end的值,使start>end。轮到线程A执行了,有效性检查OK了,开始拷贝..此时start和end的值已经不合法了。 安全

谨慎使用重载方法

java中,重载方法的选择是在编译时决定的,跟类的多态不一样。因此有些时候代码行为可能出乎咱们的意料。 this

好比以下代码输出的是三个"unknow",而不是分别输出"set""list""unknow" spa


public class Test {

	public static String classify(Set s) {
		return "set";
	}

	public static String classify(List l) {
		return "list";
	}

	public static String classify(Collection c) {
		return "unknow";
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Collection[] c = new Collection[] { new HashSet(), new ArrayList(),
				new HashMap().values() };

		for (Collection collection : c) {
			System.out.println(classify(collection)); // 重载方法的选择是在编译时决定的,由于collection的类型是Collection,因此选择第三个重载方法。
		}
	}
}
为了使如上代码按照咱们所想象的那样工做,应该在Collection的重载方法中,用instanceof判断参数的具体类型再作具体的逻辑。


对于重载方法,最好仍是别用了吧... 线程

看看java的ObjectOutputStream类,它的write方法没有采用重载,而是采用了变形方法:writeBoolean(boolean) writeInt(int) writeLong(long)

返回0长度的数组而不是null

常常能够看到以下代码:
public Cheese[] getCheeses() {
    if (cheeseInstock.size() == 0) {
    return null;
    ......
    }
}
这样,用户使用这个接口时,还要写额外代码去判断数组是否为null,这很容易出错,建议应该返回0大小的数组而不是null。
相关文章
相关标签/搜索