Java: checked vs unchecked exception explanation
I have read multiple posts on StackOverFlow about checked vs unchecked exceptions. I'm honestly still not quite sure how to use them properly.
Joshua Bloch in "Effective Java" said that
Use checked exceptions for recoverable conditions and runtime exceptions for programming errors (Item 58 in 2nd edition)
Let's see if I understand this correctly.
Here is my understanding of a checked exception:
try{
String userInput = //read in user input
Long id = Long.parseLong(userInput);
}catch(NumberFormatException e){
id = 0; //recover the situation by setting the id to 0
}
1. Is the above consider a checked exception?
2. Is RuntimeException an unchecked exception?
Here is my understanding of an unchecked exception:
try{
File file = new File("my/file/path");
FileInputStream fis = new FileInputStream(file);
}catch(FileNotFoundException e){
//3. What should I do here?
//Should I "throw new FileNotFoundException("File not found");"?
//Should I log?
//Or should I System.exit(0);?
}
4. Now, couldnt the above code also be a checked exception? I can try to recover the situation like this? Can I? (Note: my 3rd question is inside the catch
above)
try{
String filePath = //read in from user input file path
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
}catch(FileNotFoundException e){
//Kindly prompt the user an error message
//Somehow ask the user to re-enter the file path.
}
5. Why do people do this?
public void someMethod throws Exception{
}
Why do they let the exception bubble up? Isn't handling the error sooner better? Why bubble up?
EDIT: Should I bubble up the exact exception or mask it using Exception?
Below are my readings
In Java, when should I create a checked exception, and when should it be a runtime exception?
When to choose checked and unchecked exceptions
Many people say that checked exceptions (ie these that you should explicitly catch or rethrow) should not be used at all. They were eliminated in C# for example, and most languages don't have them. So you can always throw a subclass of RuntimeException
(unchecked exception)
However, I think checked exceptions are useful - they are used when you want to force the user of your API to think how to handle the exceptional situation (if it is recoverable). It's just that checked exceptions are overused in the Java platform, which makes people hate them.
Here's my extended view on the topic.
As for the particular questions:
Is the NumberFormatException
consider a checked exception?
No. NumberFormatException
is unchecked (= is subclass of RuntimeException
). Why? I don't know. (but there should have been a method isValidInteger(..)
)
Is RuntimeException
an unchecked exception?
Yes, exactly.
What should I do here?
It depends on where this code is and what you want to happen. If it is in the UI layer - catch it and show a warning; if it's in the service layer - don't catch it at all - let it bubble. Just don't swallow the exception. If an exception occurs in most of the cases you should choose one of these:
Now, couldn't the above code also be a checked exception? I can try to recover the situation like this? Can I?
It could've been. But nothing stops you from catching the unchecked exception as well
Why do people add class Exception
in the throws clause?
Most often because people are lazy to consider what to catch and what to rethrow. Throwing Exception
is a bad practice and should be avoided.
Alas, there is no single rule to let you determine when to catch, when to rethrow, when to use checked and when to use unchecked exceptions. I agree this causes much confusion and a lot of bad code. The general principle is stated by Bloch (you quoted a part of it). And the general principle is to rethrow an exception to the layer where you can handle it.
Whether something is a "checked exception" has nothing to do with whether you catch it or what you do in the catch block. It's a property of exception classes. Anything that is a subclass of Exception
except for RuntimeException
and its subclasses is a checked exception.
The Java compiler forces you to either catch checked exceptions or declare them in the method signature. It was supposed to improve program safety, but the majority opinion seems to be that it's not worth the design problems it creates.
Why do they let the exception bubble up? Isnt handle error the sooner the better? Why bubble up?
Because that's the entire point of exceptions. Without this possibility, you would not need exceptions. They enable you to handle errors at a level you choose, rather than forcing you to deal with them in low-level methods where they originally occur.
Is the above consider a checked exception? No The fact that you are handling an exception does not make it a Checked Exception if it is a RuntimeException.
Is RuntimeException an unchecked exception? Yes
Checked Exceptions are subclasses of java.lang.Exception Unchecked Exceptions are subclasses of java.lang.RuntimeException
Calls throwing checked exceptions need to be enclosed in a try{} block or handled in a level above in the caller of the method. In that case the current method must declare that it throws said exceptions so that the callers can make appropriate arrangements to handle the exception.
Hope this helps.
Q: should I bubble up the exact exception or mask it using Exception?
A: Yes this is a very good question and important design consideration. The class Exception is a very general exception class and can be used to wrap internal low level exceptions. You would better create a custom exception and wrap inside it. But, and a big one - Never ever obscure in underlying original root cause. For ex, Dont ever
do following -
try {
attemptLogin(userCredentials);
} catch (SQLException sqle) {
throw new LoginFailureException("Cannot login!!"); //<-- Eat away original root cause, thus obscuring underlying problem.
}
Instead do following:
try {
attemptLogin(userCredentials);
} catch (SQLException sqle) {
throw new LoginFailureException(sqle); //<-- Wrap original exception to pass on root cause upstairs!.
}
Eating away original root cause buries the actual cause beyond recovery is a nightmare for production support teams where all they are given access to is application logs and error messages. Although the latter is a better design but many people dont use it often because developers just fail to pass on the underlying message to caller. So make a firm note: Always pass on the actual exception
back whether or not wrapped in any application specific exception.
On try-catching RuntimeExceptions
RuntimeExceptions as a general rule should not be try-catched. They generally signal a programming error and should be left alone. Instead the programmer should check the error condition before invoking some code which might result in a RuntimeException. For ex:
try {
setStatusMessage("Hello Mr. " + userObject.getName() + ", Welome to my site!);
} catch (NullPointerException npe) {
sendError("Sorry, your userObject was null. Please contact customer care.");
}
This is a bad programming practice. Instead a null-check should have been done like -
if (userObject != null) {
setStatusMessage("Hello Mr. " + userObject.getName() + ", Welome to my site!);
} else {
sendError("Sorry, your userObject was null. Please contact customer care.");
}
But there are times when such error checking is expensive such as number formatting, consider this -
try {
String userAge = (String)request.getParameter("age");
userObject.setAge(Integer.parseInt(strUserAge));
} catch (NumberFormatException npe) {
sendError("Sorry, Age is supposed to be an Integer. Please try again.");
}
Here pre-invocation error checking is not worth the effort because it essentially means to duplicate all the string-to-integer conversion code inside parseInt() method - and is error prone if implemented by a developer. So it is better to just do away with try-catch.
So NullPointerException and NumberFormatException are both RuntimeExceptions, catching a NullPointerException should replaced with a graceful null-check while I recommend catching a NumberFormatException explicitly to avoid possible introduction of error prone code.
链接地址: http://www.djcxy.com/p/17966.html上一篇: 钻石操作员不受支持
下一篇: Java:检查与未经检查的异常说明