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

本文介绍了Java编程中的几个实用技巧,包括如何正确检查参数的有效性、何时使用保护性拷贝、谨慎使用重载方法以及为何应避免返回null等。通过这些技巧,可以提高代码的质量和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

检查参数的有效性

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值