在类库中很多函数设计很巧妙,至今我还在体会他们的设计哲学是怎么样的,比如关于LinkedList的,里面有一个函数:
返回第一个元素,如果之前我没看过这段代码的话,让我自己写的话,我可能会返回一个null值,但类库里是抛出一个异常。很多类库的函数(比如remove操作等)都是这样设计的。
仔细想想这样确实有道理。
因为返回null和抛出异常实际上两个是两种不同的含义,抛出异常说明的是做了不正确的操作,而返回null值只说明结果没取到,或值不确定。
但如果说不抛出异常,而用返回值null表示没有元素也是可以的。但我觉得这样可能比较别扭,因为这有点脱离本身这个函数的本意了(职责驱动设计?),并且如果用户对这个返回值没做检查就拿去用的话那就引起后续的麻烦(否则,api里还要告诉用户这里应该加上空值检查),那这样还不如在问题发生的早期就告诉用户已经发生了问题了。
这让我想起了断言式编程(防御性编程?),应该说类库的作者很无敌。。
不过后来有几个函数又让我很困惑,第一是peek和element函数都是取首元素,但为什么要做两个版本(仅仅是为了覆盖实现Deque中的这两个接口吗?),而且一个可能抛异常,而另一个确实返回null值。还有peekFirst。。。
删除方面有poll和remove()等,也同样是这个问题,晕啊。。。
public E getFirst() {
if (size==0)
throw new NoSuchElementException();
return header.next.element;
}
返回第一个元素,如果之前我没看过这段代码的话,让我自己写的话,我可能会返回一个null值,但类库里是抛出一个异常。很多类库的函数(比如remove操作等)都是这样设计的。
仔细想想这样确实有道理。
因为返回null和抛出异常实际上两个是两种不同的含义,抛出异常说明的是做了不正确的操作,而返回null值只说明结果没取到,或值不确定。
但如果说不抛出异常,而用返回值null表示没有元素也是可以的。但我觉得这样可能比较别扭,因为这有点脱离本身这个函数的本意了(职责驱动设计?),并且如果用户对这个返回值没做检查就拿去用的话那就引起后续的麻烦(否则,api里还要告诉用户这里应该加上空值检查),那这样还不如在问题发生的早期就告诉用户已经发生了问题了。
这让我想起了断言式编程(防御性编程?),应该说类库的作者很无敌。。
不过后来有几个函数又让我很困惑,第一是peek和element函数都是取首元素,但为什么要做两个版本(仅仅是为了覆盖实现Deque中的这两个接口吗?),而且一个可能抛异常,而另一个确实返回null值。还有peekFirst。。。
删除方面有poll和remove()等,也同样是这个问题,晕啊。。。