Currently I\'m catching only generic exceptions, but i want change this to catch the specific exceptions, but what is the advantage of this?
A good example that shows the ability to handle issues based on the type of issue that occurred:
try {
// open a file based on its file name
} catch (FileNotFoundException e) {
// indicate that the user specified a file that doesn't exist.
// reopen file selection dialog box.
} catch (IOException e) {
// indicate that the file cannot be opened.
}
while the corresponding:
try {
// open a file based on its file name.
} catch (Exception e) {
// indicate that something was wrong
// display the exception's "reason" string.
}
The latter example provides no means for handling the exception based on what issue occurred. All issues get handled the same way.
The difference between performing a general try/catch statement and catching a specific exception (e.g. a FileNotFoundException) typically depend on what errors you need to handle and what errors you don't need to worry about. For instance:
catch (Exception e) { //A (too) general exception handler
...
}
The code above will catch EVERY exception that is thrown inside of the try statement. But maybe you don't want to handle every error. What can you do with an "OutOfMemory" exception?
A better method of error handling would be to perform some default action if the error is unknown or something you can't do anything about, and perform another action if you discover that you can do "Plan B" if you catch.
For example, assume you are trying to open a file, but the file doesn't exist. You can catch the FileNotFoundException and create a new blank file as below:
catch (FileNotFoundException e) { //A specific exception handler
//create a new file and proceed, instead of throwing the error to the user
}catch (Exception e) { //For all other errors, alert the user
...
}
This has been the most effective and user-friendly method of error checking that I've used in the past.
Catching specific exceptions allows you to tailor specific responses to each case.
At a logical level, a series of catch blocks is the same as having one catch block, and then writing your own conditional logic inside the single catch block. Note that the conditional logic would also have to cast the exception as specific subtypes if you want access to detailed information declared within the subtype.
The few disadvantages of catching each exception separately include the whole try - catch structure growing very large and making the logic of the containing method harder follow, and having to repeat code in many or all of the separate catch blocks (for example, logging the exception).
In certain cases, the complexity of some underlying API warrants both the handling of all the different exceptions and the extraction of the try-catch structure into a utility method. For example, method invocation through reflection seems to regularly warrant having facade APIs.
At an API design level, there is always a balancing act between
The problem with catching generic exceptions is that you end up catching (and often mishandling) unexpected exception. For example:
public String readFile(File file) {
try {
Reader r = new FileReader(file);
// read file
return ...; // the file contents
} catch (Exception ex) {
// file not found ...
return "";
}
}
As you can see, the above is written on the assumption that the only way that the code inside the try
can fail is if the file is missing, or can't be opened for some reason. In fact, if the method is called with a null
file, or if there is some bug in the code that reads the file, NPEs and other unchecked exceptions are possible. Thus the code is going to hide bugs by catching Exception
.
The correct version of the code above would catch IOException
(or maybe FileNotFoundException
) and let the unexpected exceptions propagate.
If you have a block of code which can throw different exceptions, and you surround that with a general try {} catch {Exception e}, you won't know what exactly happened and how you should handle the error.
If you plan on multiple people using your application, having specific exceptions will let you know exactly where your program failed when under the control of someone else. but aside from that, if the program is only for yourself, you can just run it through a debugger, although being in the habit of making very descriptive and unambiguous error handling is a great on to have, if you ever do plan on taking your programming to the masses :)