My question is about try-catch blocks on a simple division by zero example. You see the first line of try? If I cast any of those two variables to the double the program does not recognize the catch block. In my opinion, whether I cast or not only the catch block must be executed. What is wrong on this code?
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");
}
}
Divide by zero is valid for floating point numbers.
- 1/0 yields Infinity.
- (-1)/0 yields -Infinity.
- 0/0 yields NaN.
These "numbers" are properly defined in IEEE 754.
Integer division by zero, on the other hand, throws because one cannot represent infinity as an int
.
I'd suggest verifying:
if (divisor != 0) {
// calculate
}
rather than catching an exception
Since you are a self-proclaimed "newbie", I think it would be a good idea to point out some broader issues with your code. (I know it is not production code, but just lets assume for the sake of argument that it was.)
If an exception is expected, it is usually simpler, clearer and more efficient if you detect the condition that will give rise to the exception. In this case, if you expect divisor
to occasionally be zero it is better to test it before doing the division.
On the other hand, if an exception is totally unexpected (i.e. a "bug") the best strategy is to let the exception propagate to the outermost level. At that point your application catch should catch all exceptions, log the exception stacktrace and bail out.
Apart from the previous bullet, it is a bad idea to catch Exception
, RuntimeException
, Throwable
or Error
. Doing this will catch a large number of exceptions that you probably don't intend to catch. In this case, since you are expecting an ArithmeticException
, you should catch just that.
It is rarely correct to use float
or double
in financial applications. These types are not exact, but financial applications typically require quantities of money to be handled exactly.
More generally, floating point numbers are inherently hard for lay people (and newbies) to understand. A lot of the "truths" that people expect to hold actually don't hold. For example, a floating point calculation of 1.0/3.0 + 1.0/3.0 + 1.0/3.0
does not give 1.0
. Similarly (as you discovered) division by zero behaves differently. If you want to use floating point safely, you need to understand the pitfalls.
EDIT elaborating the first point in response to @Jay's comment.
First, I deliberately used the word "usually". There are cases where avoiding throwing the expected exception achieves nothing.
Having said that, you often don't want a generic "expected" exception to happen even if your application cannot deal with the situation immediately. For example, if the OP's code was part of something larger, it may be better to explicitly throw IllegalArgumentException
(if this is a violation of an API contract) or some checked UserEnteredRubbishException
if we know that this is a result of bad user input (and there is some opportunity to report / correct it).
The fact that we are "expecting" an exception means by definition that we know more about it than (say) a generic ArithmeticException
would say. If we allow a generic exception to propagate, it makes it harder for a catch block many stack frames to act appropriately. In this case for example, the remote catch block could not diagnose the cause of the divide-by-zero with any certainty. The ArithmeticException
might have come from a different part of the application, and might not even be a divide-by-zero! The way to address is to explicitly throwing a more specific exception.
The answer lies in your program's own output - it prints "Infinity" for result
. This is because Java only disallows integer division by zero - floating point division by zero is legal and produces Infinity
.
See the documentation of Double and Float for the POSITIVE_INFINITY
and NEGATIVE_INFINITY
constants.
Only division by zero with integers will raise an ArithmeticException.
Division by zero with double or float will result in Infinity.
Because dividing two doubles returns a Infinity, but doesn't throw. You can use isInfinite() to check for this. However, the appropriate solution (as already noted) is to check the denominator before the division.
No one should try to expect RuntimeException
to be thrown from their code. These Exception
s can be (and should be) avoided easily.