博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Effective Java读书笔记》--方法
阅读量:6768 次
发布时间:2019-06-26

本文共 2088 字,大约阅读时间需要 6 分钟。

hot3.png

检查参数的有效性

方法在执行前,首先对参数进行检查,如果参数不合法,应该清楚地以一个适当的异常指明错误的原因。
对于非公有方法,调用者应该保证传入的参数是合理的,所以应该以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非法情况出现。

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

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

谨慎使用重载方法

java中,重载方法的选择是在编译时决定的,跟类的多态不同。所以有些时候代码行为可能出乎我们的意料。

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

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。

转载于:https://my.oschina.net/u/1453800/blog/263037

你可能感兴趣的文章