问题
I have learned from various tutorial that "If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception."
I really want to see the effectiveness of previous statement through some code examples. e.g.
try {
br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
Here, IOException is checked Exception.So, how I'm supposed to recover when this Exception occurs? Here, I'm excluding the exception logging,exception re-throwing tasks since they are not actually recovering i.e making things right. So, what modification should be applied here to recover from it?
If there's a way to recover from it, then the same kind of approach can be applied to the following code :
try{
Integer.parseInt("ghg4");
}catch(NumberFormatException nfe){
}
Here NumberFormatException is a Runtime/unchecked exception.So if there's a way to recover from it, then why is it declared as Runtime exception in the first place?
回答1:
I see three types of exceptions. At the one extreme are the ones you can't do anything about, like a NullPointerException. You're going to handle this at a very high level in your code or not at all. It would be ridiculous to check it.
At the other end are the ones that provide meaningful information. They're sort of a way of returning a value, sometimes a complex one, when the method already has a return value. They're also an easy way of jumping up the call stack. (I could write a book about this, but I'll stop here.) An EOFException ought to be a good example of this. Files have their ends, you're going to hit it sooner or later, and you don't want to have to check it every time you do a read. In this case, a checked exception is called for. (I think user1291492 would agree with me on this.) It can happen, and anybody calling a read method should be prepared for it. They'll much prefer a compiler error to a runtime error.
Now, with this type of exception, you do not want to put in a stack trace!!! It costs lots of time. The caller just needs to know he hit an EOF, not where in the depths of the IO system it happened! Further, unless there is interesting information to be returned, the exception itself ought to be a final static
reference, generated once and used for every EOF that happens.
The third type, in the middle, are the ones the Java libraries use, like the real EOFException. They make no sense. Either the caller expects never to get an EOF (he put his own marker out there, for instance) and EOFException is of the same nature as a NullPointerException, or he expects it and doesn't need the hassle and lost processing time of a stack trace. I think the problem is that the Java designers themselves--and I have to admit to having this problem myself when I think about it--which is rarely--weren't sure which of the first two categories these exceptions might fall into. Even in the same program, in one place the EOFException might indicate the total failure of a program. In another, it might be the normal way to find out that a file has been read. So the end result is a ton of exceptions that do both jobs and do them poorly, forcing the programmer to use try
and catch
and throws
when they can't do anything anyway and handing them elaborate stack traces they don't need.
Addition: I should pehaps note explicitly that you can recover from the real EOFException by simply accepting that you have finished reading the file and carrying on, possibly with a break
statement in the catch
block. However, there are other, proper ways to catch an EOF, so an EOFException usually means a real problem like a NullPointerException. Oddly, the way I use NumberFormatException, I think it should be checked. Getting "AAA" when I want a number is very common, a user error, not a programming error.
回答2:
c# did away with checked exceptions, which I think was a good idea.
In code that I've written, I have mostly followed the c# pattern, extending everything from RuntimeException. However there are a few places where I have utilized checked exceptions to force myself and anyone using my code to respond to what is more of a "normal" exceptional condition
回答3:
There is no explicit border between RuntimeException and Exception. Generally speaking, overusing descendants of Exception leads either to chains of catch clauses (e.g. for reflection handling code) or just catch (Exception e)
which doesn't care about particular types. There are many different practices and this question is controversial - i.e. it's not that simple and there is no the only one right way to design exceptions in your application.
I keep the following rule:
If an exception is going to be handled separately and is distinguishable from a simple input data error or something like that - it's a checked exception.
If an exception is caused by obviously wrong input conditions or bug in the code (like NPE) - then it's runtime exception.
From this logic, for example, I would have made IOException a descendant of RuntimeException.
UPDATE: This is not black and white regarding IOException. But some of IOE descendants (like FileNotFoundException, MalformedURLException etc.) - are definitely just bad input. Also it makes things annoying when you work with ByteArray IO Streams (or similar ones) to handle IOE which never happen.
来源:https://stackoverflow.com/questions/9947575/when-should-checked-exception-unchecked-exception-be-chosen