Java未经检查/检查异常澄清

时间:2011-02-21 20:30:20

标签: java exception throw checked unchecked

我一直在阅读未经检查和已检查的问题,没有一个在线资源真正清楚这些差异以及何时使用这两者。

根据我的理解,它们都会在运行时抛出,它们都代表超出逻辑预期范围的程序状态,但必须明确捕获已检查的异常,而未经检查的异常则不会。

我的问题是,假设为了论证我有一个方法来划分两个数字

double divide(double numerator, double denominator)
{    return numerator / denominator;    }

以及需要在某处使用divison的方法

void foo()
{    double a = divide(b, c);    }

谁负责检查分母为零的情况,是否应检查或取消选中异常(忽略Java内置的分区检查)?

那么,divide方法是声明为是还是

double divide(double numerator, double denominator) throws DivideByZeroException
{
    if(denominator == 0) throw DivideByZeroException
    else ...
}

void foo()
{
    try{
        double a = divide(b, c);
    }
    catch(DivideByZeroException e)
    {}
}

或没有经过检查的例外,原样如下:

double divide(double numerator, double denominator)
{
    if(denominator == 0) throw DivideByZeroException
    else ...
}

void foo()
{
    if(c != 0)
       double a = divide(b, c);
}

并允许foo除以零检查?

这个问题最初出现在我写的数学程序中,用户输入的数字和逻辑类执行计算。我不知道GUI是否应该立即检查不正确的值,或者内部逻辑是否应该在计算过程中捕获它们并抛出异常。

6 个答案:

答案 0 :(得分:7)

确实有趣的话题!

在阅读并尝试了大量处理一般错误和异常的方法后,我学会了程序员错误预期错误之间的区别。

永远不应该抓住程序员错误,而应该尽早崩溃(!)。程序员错误是由逻辑错误引起的,应该修复根本原因。

应始终捕获

预期错误。此外,当捕获到预期错误时,必须为用户显示一条消息。这有一个重要的含义 - 如果预期的错误不应该显示错误,最好检查方法是否会抛出而不是让它抛出。

所以应用到你的例子我会想“这应该如何看待用户?”

  1. 如果应该显示错误消息(在浏览器输出,控制台,消息框中),我会抛出异常并将其作为尽可能接近UI 并输出错误消息。
  2. 如果没有显示错误信息,我会检查输入而不是扔。
  3. 旁注:我从不抛出DivideByZeroExceptionNullPointerException - 我让JVM为我抛出这些东西。在这种情况下,您可以酿造自己的异常类或使用合适的内置检查异常。

答案 1 :(得分:1)

我最喜欢讨论Java中已检查和未检查异常之间的哲学差异:

http://www.javapractices.com/topic/TopicAction.do?Id=129

答案 2 :(得分:1)

Java异常仅由编译器检查,但java设计者决定将它们分成多个类别,基本上涉及超类被扩展

  • java.lang.Exception - 称为已检查例外
  • java.lang.RuntimeException称为UNchecked异常 - 作为奖励java.land.RuntimeException扩展java.lang.Exception(以简化catch块中的处理,而不仅仅是)
  • java.lang.Error - 错误,也是未经检查的,很少需要由用户空间代码处理,但了解它们及其差异是一个重要的优点。它们包括(最着名的):链接错误,堆栈溢出,内存不足,断言错误
  • java.lang.Throwable - Checked!和所有异常的母亲,很少需要直接将其子类化,但有些原因不明原因

因此需要声明异常并处理正确的传播(仅在编译级别),未经检查的那些是自动传播的,除非需要,否则开发人员不会提供处理。

通常情况下会检查已检查的内容,并且需要在Java中加入冗长的代码。

最糟糕的做法包括:catch (Throwable t){},由于很多原因,除非必要,否则通常不会处理错误,而且大多数错误通常都会导致线程死亡。

答案 3 :(得分:1)

假设由于数学运算而抛出了已检查的异常。 E.g部门(根据您的帖子)。
这意味着每个整数除法应出现在try块中! 实际上,division可以抛出一个ArithmeticException,它是未经检查的异常,所以不需要捕获它 实际上你不应该抓住它,因为这是一个特殊情况,通常只能通过代码修正来解决。
在您的情况下,您的代码应该已经做了之前以实际除以零的内容 如果你已经达到允许实际除零的步骤,那么你无能为力。该程序是错误的,最好修复,而不是尝试以某种方式通过抛出/捕获异常来伪装它

答案 4 :(得分:0)

简短的回答,因为一些利弊被命名:这是个人或组织风格的问题。没有一个在功能上优于另一个。您(或您的项目)必须自行决定是否使用已检查或未检查的例外,或两者都有。

Oracle's Java Tutorial建议您对应用程序可以从中恢复的所有错误使用已检查的异常,并对应用程序无法从中恢复的错误进行未经检查的异常。但根据我的经验,大多数应用程序可能会从大多数(可能不在启动期间)异常中恢失败的操作将被中止但应用程序仍然存活。

我宁愿只使用已检查的异常或未经检查的异常。混合可能导致混淆和使用不一致。务实。在你的情况下做有意义的事情。

答案 5 :(得分:0)

永远不要明确抛出RuntimeException。如果您认为您需要让运行时执行此操作而不是使用throw