在Java方法中抛出异常而不是返回

lik*_*ern 8 java coding-style

Deque根据Algorithms, Coursera的第1部分,我正在编写关于Java的课程.目前我的基于数组的方法DequeremoveLast():

public Item removeLast() {
    if (size() == array.length / 4) {
        resize(array.length / 2);
    }

    if (head != tail) {
        Item tmp = array[--head];
        array[head] = null;
        return tmp;
    }
    throw new NoSuchElementException("Stack underflow");
}
Run Code Online (Sandbox Code Playgroud)

如果 head == tailmeans Deque是空的,我根据作业规范抛出异常,在方法结束而不是return 语句.这段代码给出了关于不变量(head != tail)的直接意图.

另一方面,方法可能会像这样重写:

public Item removeLastRewritten() {
    if (size() == array.length / 4) {
        resize(array.length / 2);
    }

    if (head == tail) {
        throw new NoSuchElementException("Stack underflow");
    }

    Item tmp = array[--head];
    array[head] = null;
    return tmp;
}
Run Code Online (Sandbox Code Playgroud)

在我看来,removeLast由以下原因更清楚地写出:

  1. 坚持悲观的场景 - always fail, only if ...这是更可靠的方法,特别是当方法代码会扩大并变得更加复杂时.
  2. 在不变tail != head和后续if {}代码块之间提供更清晰的链接.

我有以下问题:

  1. 哪种方法更好?
  2. 这样写是一种合适/好的做法removeLast吗?
  3. 什么被认为是Java的最佳实践?是否有任何代码风格(我找不到)?

kla*_*aar 1

它看起来很奇怪的原因是因为您省略了块else的块,这将合并两个方法中块if之后的剩余部分。if您可以在这里逃脱的原因是因为抛出的异常会扰乱您的方法的流程。

我认为最好不要依赖它,而是友善地if-else直观地使用这些块。

public Item removeLastRewrittenAgain() {
    if (size() == array.length / 4) {
        resize(array.length / 2);
    }

    if (head != tail) { // invert the if-else block if preferred, it would not make any difference
        Item tmp = array[--head];
        array[head] = null;
        return tmp;
    } else {
        throw new NoSuchElementException("Stack underflow");
    }
}
Run Code Online (Sandbox Code Playgroud)

我不太喜欢在方法结束之前抛出异常的另一个原因是我坚信并因此彻底使用 的概念a single point of exit,这意味着我不会将方法留在中间的某个地方,我认为这更困难供不熟悉代码的人阅读。

返回值(或抛出异常)的一个地方:方法的最底部。