14

私の質問は、ゼロによる単純な除算の例での try-catch ブロックに関するものです。try の最初の行が見えますか? これら 2 つの変数のいずれかを double にキャストすると、プログラムは 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ときどきゼロになることが予想される場合は、除算を行う前にテストすることをお勧めします。

  • 一方、例外がまったく予期しないもの (つまり「バグ」) である場合、最善の戦略は、例外を最も外側のレベルに伝播させることです。その時点で、アプリケーションのキャッチはすべての例外をキャッチし、例外スタックトレースをログに記録して救済する必要があります。

  • 前の箇条書きとは別に、ExceptionRuntimeExceptionThrowableまたはをキャッチするのは悪い考えErrorです。これを行うと、おそらくキャッチするつもりのない多数の例外がキャッチされます。この場合、 を期待しているので、それArithmeticExceptionだけをキャッチする必要があります。

  • 金融アプリケーションでの使用が正しいことはめったにありませんfloatdoubleこれらのタイプは正確ではありませんが、金融アプリケーションでは通常、金額を正確に処理する必要があります。

  • より一般的に言えば、浮動小数点数は一般の人 (および初心者) にとって本質的に理解しにくいものです。人々が保持することを期待している「真実」の多くは、実際には保持されていません。たとえば、 の浮動小数点計算で1.0/3.0 + 1.0/3.0 + 1.0/3.0は は得られません1.0。同様に(あなたが発見したように)ゼロによる除算は異なる動作をします。浮動小数点を安全に使用するには、落とし穴を理解する必要があります。

@Jayのコメントに応じて、最初のポイントを詳しく編集してください。

まず、わざと「いつも」という言葉を使いました。予期される例外のスローを回避しても何も達成されない場合があります。

そうは言っても、アプリケーションが状況にすぐに対処できない場合でも、一般的な「予期される」例外が発生することを望まないことがよくあります。たとえば、OP のコードがより大きなものの一部である場合は、明示的にスローするIllegalArgumentException(これが API コントラクトの違反であるUserEnteredRubbishException場合) か、これが不適切なユーザー入力の結果であることがわかっている場合 (および報告/修正する機会があります)。

例外を「期待」しているという事実は、定義上、ジェネリックが言うよりも(たとえば)それについて知っていることを意味しArithmeticExceptionます。一般的な例外の伝播を許可すると、catch ブロックの多くのスタック フレームが適切に動作することが難しくなります。たとえば、この場合、リモート キャッチ ブロックはゼロ除算の原因を確実に診断できませんでした。は、アプリケーションの別の部分から発生した可能ArithmeticException があり、ゼロ除算でさえない可能性があります! 対処する方法は、より具体的な例外を明示的にスローすることです。

于 2010-02-14T00:12:08.063 に答える
3

答えはあなたのプログラム自身の出力にあります - それは "Infinity" を出力しますresult. これは、Java がゼロによる整数除算のみを許可しないためです。ゼロによる浮動小数点除算は正当であり、生成されますInfinity

および定数については、 DoubleおよびFloatのドキュメントを参照してください。POSITIVE_INFINITYNEGATIVE_INFINITY

于 2010-02-13T21:54:13.593 に答える
2

整数によるゼロ除算のみが ArithmeticException を発生させます。double または float でゼロ除算すると、Infinityになります。

于 2010-02-13T21:55:22.360 に答える
1

2 つの double を除算すると Infinity が返されますが、スローされないためです。isInfinite()を使用してこれを確認できます。ただし、適切な解決策は (既に述べたように) 除算の前に分母をチェックすることです。

于 2010-02-13T21:54:33.877 に答える
0

RuntimeExceptionコードからスローされることを期待しようとするべきではありません。これらExceptionの s は簡単に回避できます (回避する必要があります)。

于 2010-02-14T00:35:49.807 に答える