14

我的问题是关于简单除零示例中的 try-catch 块。你看到第一行尝试了吗?如果我将这两个变量中的任何一个转换为双精度,程序将无法识别 catch 块。在我看来,无论我是否强制转换,都必须执行 catch 块。这段代码有什么问题?

public static void main(String[] args) {

    int pay=8,payda=0;  

    try {

        double result=pay/(double)payda; // if I cast any of the two variables, program does not recognize the catch block, why is it so?
        System.out.println(result);
        System.out.println("inside-try");

    } catch (Exception e) {

        System.out.println("division by zero exception");
        System.out.println("inside-catch");

    }
}
4

7 回答 7

24

除以零对浮点数有效。

  • 1/0 产生无穷大。
  • (-1)/0 产生 -Infinity。
  • 0/0 产生 NaN。

这些“数字”在 IEEE 754 中得到了正确定义。

另一方面,整数除以零会抛出,因为不能将无穷大表示为int

于 2010-02-13T21:54:02.217 回答
14

我建议验证:

if (divisor != 0) {
    // calculate
}

而不是捕捉异常

于 2010-02-13T21:54:30.897 回答
8

由于您自称是“新手”,因此我认为指出您的代码中一些更广泛的问题是个好主意。(我知道这不是生产代码,但只是为了争论而假设它是。)

  • 如果预期会出现异常,如果您检测到会导致异常的条件,通常会更简单、更清晰、更高效。在这种情况下,如果您希望divisor偶尔为零,最好在进行除法之前对其进行测试。

  • 另一方面,如果异常完全出乎意料(即“错误”),最好的策略是让异常传播到最外层。此时,您的应用程序捕获应该捕获所有异常,记录异常堆栈跟踪并退出。

  • 除了上一个项目符号之外,抓住、Exception或是个坏主意。这样做会捕获大量您可能不打算捕获的异常。在这种情况下,既然你期待一个,你应该抓住它。RuntimeExceptionThrowableErrorArithmeticException

  • 在金融应用程序中使用float或使用很少是正确的。double这些类型并不准确,但金融应用程序通常需要准确处理大量资金。

  • 更一般地说,浮点数对于外行(和新手)来说本来就很难理解。人们期望持有的许多“真理”实际上并不成立。例如,浮点计算1.0/3.0 + 1.0/3.0 + 1.0/3.0不给出1.0. 同样(正如您所发现的)除以零的行为不同。如果你想安全地使用浮点数,你需要了解其中的陷阱。

编辑详细说明第一点以回应@Jay 的评论。

首先,我特意使用了“通常”这个词。在某些情况下,避免抛出预期的异常也无济于事。

话虽如此,您通常不希望发生一般的“预期”异常,即使您的应用程序无法立即处理这种情况。例如,如果 OP 的代码是更大的东西的一部分,最好显式地抛出IllegalArgumentException(如果这违反了 API 合同),或者UserEnteredRubbishException如果我们知道这是错误的用户输入的结果(并且有有机会报告/纠正它)。

我们“期待”一个异常的事实意味着我们对它的了解比(比如说)泛型ArithmeticException所说的要多。如果我们允许一个通用异常传播,它会使一个 catch 块更难处理许多堆栈帧。例如,在这种情况下,远程 catch 块无法确定被零除的原因。ArithmeticException 可能来自应用程序的不同部分,甚至可能不是被零除!解决的方法是显式抛出更具体的异常。

于 2010-02-14T00:12:08.063 回答
3

答案在于您的程序自己的输出 - 它为result. 这是因为 Java 只不允许整数除以零 - 浮点除以零是合法的并产生Infinity

有关and常量,请参阅DoubleFloat的文档。POSITIVE_INFINITYNEGATIVE_INFINITY

于 2010-02-13T21:54:13.593 回答
2

只有用整数除以零才会引发 ArithmeticException。用 double 或 float 除以零将导致Infinity

于 2010-02-13T21:55:22.360 回答
1

因为除以两个双打返回一个无穷大,但不抛出。您可以使用isInfinite()来检查这一点。但是,适当的解决方案(如前所述)是在除法之前检查分母。

于 2010-02-13T21:54:33.877 回答
0

没有人应该试图期望RuntimeException从他们的代码中被抛出。这些Exceptions 可以(并且应该)很容易地避免。

于 2010-02-14T00:35:49.807 回答