Java unchecked/checked exception clarification
I've been reading about unchecked versus checked questions, none of the online resources have b开发者_如何学JAVAeen truly clear about the difference and when to use both.
From what I understand, both of them get thrown at runtime, both of them represent program states that are outside the expected bounds of the logic, but checked exceptions must be explicitly caught while unchecked ones do not.
My question is, suppose for argument's sake I have a method that divides two numbers
double divide(double numerator, double denominator)
{ return numerator / denominator; }
and a method that requires divison somewhere
void foo()
{ double a = divide(b, c); }
Who is responsible for checking the case of the denominator being zero, and should an exception be checked or unchecked (ignoring Java's built in divison checks)?
So, would the divide method be declared as is or as
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)
{}
}
or without a checked exception, as is:
double divide(double numerator, double denominator)
{
if(denominator == 0) throw DivideByZeroException
else ...
}
void foo()
{
if(c != 0)
double a = divide(b, c);
}
and allow foo to make the divide by zero check?
This problem originally arose in a mathematical program I wrote in which users entered numbers and logic classes performed calculations. I was never sure whether the GUI should check immediately for improper values, or whether the internal logic should catch them during calculation and throw exceptions.
Interesting topic indeed!
After reading and trying lots of way to deal with errors in general and exceptions specifically I learned to differ between programmer errors and a expected errors.
Programmer errors should never be caught, but rather crash (!) early and hard. A programmer error is due to a logical fault, and the root cause should be fixed.
Expected errors should always be caught. Also when a expected error is caught a message must be displayed for the user. This has an important implication - If a expected error should not display an error, it's better to check whether the method will throw instead of letting it throw.
So applied to your example I would think "How should this look to the user?"
- If a error-message should be displayed (in the browser output, console, messagebox) I would throw an exception and catch it as close to the UI as possible and output the error-message.
- If no error message should be displayed I would check the input and not throw.
On a sidenote: I never throw DivideByZeroException
nor NullPointerException
- I let the JVM throw those for me. In this case you could brew your own exception-class or use a suitable built-in checked exception.
My favorite discussion on the difference in philosophy between checked and unchecked exceptions in Java:
http://www.javapractices.com/topic/TopicAction.do?Id=129
Assume that a checked exception is thrown as a result of a mathematical operation. E.g division (as per your post).
This would mean that every integer division should appear in a try block!
Actually division can throw an ArithmeticException which is unchecked exception so there is no need to catch it.
Actually you should not catch it, since it is an exceptional condition that occured and usually can only be solved by code correction.
In your case your code should have done something prior to actually divide by zero.
If you have reached the step where you allow to actually do the division by zero then there is nothing you can do. The program is erroneous and it is best to be fixed than try to somehow disguise it by throwing/catching an exception
Java exceptions are checked only by the compiler, however java designers decided to split them into multiple categories, basically involving the superclass being extended
java.lang.Exception
- known as checked exceptionsjava.lang.RuntimeException
known as UNchecked exceptions - as bonus java.land.RuntimeException extends java.lang.Exception (to ease the handling incatch
blocks, and not only)java.lang.Error
- errors, also unchecked and rarely needed to be handled by user-space code, but knowing them and their variance is a major plus. They include (most famous): linkage error, stackoverflow, out of memory, assertion errorsjava.lang.Throwable
- Checked! and the mother of all exceptions, few need to directly subclass it, but some does for unknown reasons
So it's about need to declare the exceptions and taking care of proper propagation (on compile only level), unchecked ones are auto-propagated and the developer is not expected to provide handling of unless needed.
Checked ones are generally expected to happen and require extra verbosity in the java, already fluffy code.
Worst practices include: catch (Throwable t){}
, for many a reason, usually errors shall not be handled unless necessary and most errors usually spell the thread death either ways.
Short answer as some pros and cons have been named: It is a matter of personal or organisational style. None is functionally better than the other. You (or your project) will have to make your own decisions about whether to use checked or unchecked exceptions, or both.
Oracle's Java Tutorial advices you to use checked exceptions for all errors the application can recover from, and unchecked exceptions for the errors the application cannot recover from. But from my experience most applications may recover from most (maybe not during startup) exceptions. The action that failed will be aborted but the application stays alive.
I would rather only use either checked exceptions or unchecked exceptions. Mixing may result in confusion and inconsistent use. Be pragmatic. Do what makes sense in your situation.
Never explicitly throw RuntimeException
s. If you ever think you need to then just let the runtime do it rather than using throw
.
精彩评论