繁体   English   中英

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

[英]Throw exception instead of return in Java method

根据Coursera上的算法,第1部分 ,我正在Java上编写Deque类。 目前,我基于数组的Deque具有方法removeLast()

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");
}

如果head == tail表示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;
}

我认为removeLast是由以下原因更清楚地编写的:

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

我有以下问题:

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

没有错误的答案。 在GrepCode中,您可以找到建议的每种口味:

  1. 在带有!=运算符的if中,并在方法结尾:

E java.util.PriorityQueue.next()

public E More ...next() {
    if (... != ...)
        throw new ConcurrentModificationException();
    ...
    if (...) {
        return lastRetElt;
    }
    throw new NoSuchElementException();
}
  1. 在if中,使用==运算符

E org.fluentlenium.core.domain.FluentList.first()

public E More ...first() {
    if (this.size() == 0) {
        throw new NoSuchElementException("Element not found");
    }
    return this.get(0);
}

为什么它看起来怪异的原因是因为你忽略了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");
    }
}

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

返回值(或引发异常)的一个地方:方法的最底层。

如果您明确提及else ,则无论选择如何,您的代码都将更具可读性。

然后是两难

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

if (head == tail) {
    throw new NoSuchElementException("Stack underflow");
} else {
    Item tmp = array[--head];
    array[head] = null;
    return tmp;
}

在这里,我非常喜欢第二个。 当我阅读if语句的“复杂部分”时,我想知道为什么我实际上位于if 阅读第一个变体时,如果引发异常,则if的全部原因才变得显而易见。

我想你也可以通过写来解决

boolean isEmpty = head == tail;
if (!isEmpty) {
    Item tmp = array[--head];
    array[head] = null;
    return tmp;
}
throw new NoSuchElementException("Stack underflow");

但是我更喜欢在您知道有问题时立即引发异常的版本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM