In the above code, the first line in the tryblock can throw FileNotFoundException if the specified file could not be located on disk; and the next two lines can throw IOException if an error occurred during the reading and closing the file. Hence there are two catch blocks for handling both exceptions.
2. The order of catch blocks does matter
If the protected code can throw different exceptions which are not in the same inheritance tree, i.e. they don’t have parent-child relationship, the catch blocks can be sorted any order.However, keep in mind this rule: if the exceptions have parent-child relationship, the catch blocks must be sorted by the most specific exceptions first, then by the most general ones.In the above example, FileNotFoundException is a child of IOException so its catch block must come first. If we try to catch the IOException before FileNotFoundException, the compiler will issue an error like this:
error: exception FileNotFoundException has already been caught
Why? It’s because if we handle the most general exceptions first, the more specific exceptions will be omitted, which is not good, as Java encourages handling exceptions as much specific as possible.
3. Catching one exception for all
If we catch the most general exception first, then we also catch other exceptions which are subtypes of the general exception. For example, the above example can be re-written to catch only the IOException which is also parent of FileNotFoundException:
It’s easy to understand because Exception is the supertype of all exceptions. However, this practice is not recommended, as it makes the programmers lazy: catching one is obviously quicker than catching many. That means the programmers do not take responsibility to handle exceptions carefully. The good practice recommends catching specific exceptions so the program can handle different situations well. Java doesn’t prohibit you from catching one for all, but when doing so, you should have good reasons to do that.
4. Grouping multiple exceptions in one catch
Since Java 7, we can combine multiple exceptions in a single catch clause. This becomes very handy in case we want to apply the same handling for those exceptions. For example, the above code can be re-written using a multi-catch statement like this:
Note that we can group only un-related exceptions together. That means it’s illegal to group exceptions which have parent-child relationship. For example, it’s illegal to write a multi-catch statement like this:
try {
LineNumberReader lineReader = new LineNumberReader(new FileReader("hello.txt"));
String line = lineReader.readLine();
lineReader.close();
System.out.println(line);
} catch (FileNotFoundException | IOException ex) {
System.err.println("Find not found");
}
The compiler will complain:
error: Alternatives in a multi-catch statement cannot be related by subclassing
5. What should you do in the catch blocks?
It’s up to you to write anything inside the catch blocks. Remember the main purpose of the catch blocks is to recover the program from the exceptions and continue execution, such as notifying the user about the error, ask he or she to wait, try again or exit, etc.Typically, you can do the following things in the catch blocks (not limited to):- Print out the exception details via System.err class’ methods, then exit the method:
- Print the full stack trace of the exception and exit the method:
ex.printStackTrace();
- Log the exceptions then exit the method. You can use Java’s built-in logging functionalities or a third-part library like log4j.- Display an error message dialog in case the program is a desktop application (Swing or JavaFX).- Redirect the user to an error page in case the program is a web application (Servlets & JSP).
Nam Ha Minh is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.
Comments