私の質問は、ゼロ除算の単純な例でのtry-catchブロックについてです。試行の最初の行が表示されますか?これらの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");
}
}
ゼロ除算は浮動小数点数に有効です。
これらの「番号」は、IEEE754で適切に定義されています。
一方、ゼロによる整数除算は、無限大をint
として表すことができないためにスローされます。
確認することをお勧めします:
if (divisor != 0) {
// calculate
}
例外をキャッチするのではなく
あなたは自称「初心者」なので、コードに関するより広範な問題を指摘するのは良い考えだと思います。 (私はそれが本番コードではないことを知っていますが、議論のためにそれがそうであったと仮定しましょう。)
例外が予想される場合、例外を発生させる条件を検出すると、通常、より単純で、より明確で、より効率的になります。この場合、divisor
がときどきゼロになると予想される場合は、除算を行う前にテストすることをお勧めします。
一方、例外がまったく予期しないもの(つまり、「バグ」)である場合、最善の戦略は、例外を最も外側のレベルに伝播させることです。その時点で、アプリケーションキャッチはすべての例外をキャッチし、例外スタックトレースをログに記録して救済する必要があります。
前の箇条書きとは別に、Exception
、RuntimeException
、Throwable
、またはError
をキャッチすることはお勧めできません。これを行うと、おそらくキャッチするつもりのない多数の例外がキャッチされます。この場合、ArithmeticException
を期待しているので、それだけをキャッチする必要があります。
金融アプリケーションでfloat
またはdouble
を使用することが正しいことはめったにありません。これらのタイプは正確ではありませんが、金融アプリケーションでは通常、正確に処理するために大量のお金が必要です。
より一般的には、浮動小数点数は一般の人々(および初心者)にとって本質的に理解するのが難しいです。人々が保持することを期待する多くの「真実」は実際には保持されません。たとえば、1.0/3.0 + 1.0/3.0 + 1.0/3.0
の浮動小数点計算では、1.0
は得られません。同様に(あなたが発見したように)ゼロによる除算は異なった振る舞いをします。浮動小数点を安全に使用したい場合は、落とし穴を理解する必要があります。
[〜#〜] edit [〜#〜] @ Jayのコメントに応えて最初のポイントを詳しく説明します。
最初に、私は意図的に「通常」という言葉を使用しました。予期された例外のスローを回避しても何も達成されない場合があります。
そうは言っても、一般的な「予期される」例外が発生することを望まないことがよくありますアプリケーションが状況にすぐに対処できない場合でも。たとえば、OPのコードがより大きなものの一部である場合、明示的にIllegalArgumentException
(これがAPIコントラクトの違反である場合)をスローするか、チェックされたUserEnteredRubbishException
をスローする方がよい場合があります。これは悪いユーザー入力の結果です(そしてそれを報告/修正する機会があります)。
私たちが例外を「期待している」という事実は、定義による一般的なArithmeticException
が言うよりもそれについてもっと知っていることを意味します。一般的な例外の伝播を許可すると、catchブロックの多くのスタックフレームが適切に動作することが難しくなります。この場合、たとえば、リモートキャッチブロックはゼロ除算の原因を確実に診断できませんでした。 ArithmeticException
mightはアプリケーションの別の部分からのものであり、might notゼロ除算でさえあります!対処する方法は、より具体的な例外を明示的にスローすることです。
整数でゼロ除算するだけで、ArithmeticExceptionが発生します。 doubleまたはfloatでゼロで除算すると、Infinityになります。
2つのダブルを分割すると無限大が返されますが、スローされないためです。 isInfinite() を使用してこれを確認できます。ただし、適切な解決策(すでに述べたように)は、除算の前に分母を確認することです。
コードからRuntimeException
がスローされることを期待してはいけません。これらのException
sは簡単に回避できます(回避する必要があります)。