This post addresses exception handling in a Java development environment, the catch-or-throw rule, and general guidelines for determination of which exceptions should be thrown as they occur.
Whenever a Java method could result in a processing exception, the method can either (a) catch the exception and handle it within, or (b) throw the exception back to the source that called the method in the first place. This is known generally as the catch-or-throw rule (Lowe, 2017, p. 226). In the case of checked exceptions such as potential FileNotFoundException exceptions, the compiler will not process unless a provision has been made prior to run time (Lowe, pp. 226-229). However, the catch-or-throw dilemma applies to both checked and unchecked exceptions. Exceptions related to user input error which also cause the program to crash at run time, like NumberFomatException, should also be caught or thrown at some point (Murach, 2011, pp. 444-445). Once exceptions have been identified in a method, whether they be checked or unchecked, the developer’s next decision is whether to handle the exception at the moment it occurs, or to pass it back to the calling method.
For determination of whether to catch or throw an exception, Bloch suggests that “higher layers should catch lower-level exceptions and, in their place, throw exceptions that can be explained in terms of higher-level abstraction” (Bloch, 2018, p. 302). From this perspective, all exceptions would be connected with the software development model abstraction. For example, a method designed to retrieve data from a given file name should only throw exceptions related to issues central to retrieving the data, e.g. an improperly entered file name. Should other possible exceptions occur in the data retrieval method, such as InputMismatchException or NumberFormatException, those should be caught and dealt with directly in the data retrieval process.
For determination of where to handle an exception, Joel Murach suggests the general guideline for programmers to “throw exceptions early and catch them late” (Murach, 2011, p. 444). The throw early catch late principle can be seen at work in the example where a user interface exists to collect a known data file name, and the user interface then calls on methods to retrieve the data in the file. Once the user enters the file name in the user interface, the filename is sent to a method for retrieving data. If the name is entered correctly, the data is retrieved and returned for processing to the user interface.
But if the user has entered the file name improperly the name passed to the data retrieval method will be wrong and the data retrieval method will be faced with the dilemma of a FileNotFoundException. The practice of using a try catch block to catch the FileNotFoundException, but in the process failing to rectify the situation which caused the error, is referred to as “swallowing the exception, considered to be bad programming in practice” (Lowe, 2017, p. 230). Using the present example, the data retrieval method cannot handle the exception without referring back to the user, which is more suitably performed in the user interface.
Murach suggests “if you are at a low level in your program where you aren’t able to handle the exception, you should throw it” (2011, p. 444). For the FileNotFoundException, since the file name cannot be corrected by a data retrieval method, so the FileNotFoundException should be thrown back to the user interface, where it can be caught and corrected with user interaction.
Determining when to throw an exception can also be answered by looking at where it is appropriate to catch an exception. Generally, it is appropriate to catch exceptions in methods;
- Which are in some kind of central error-handling location,
- Which are in graphical user interface event handlers, or
- Where there is no need for the exception to interrupt the logic of your program flow (Javamex, 2019).
From this brief survey it is possible to suggest the following best practices guidelines for exception handling:
- Methods should only throw exceptions which are central to their role in the development model abstraction.
- If a central exception processing location exists, all exceptions should be thrown there.
- If an exception can be caught and rectified in the method, it likely should be.
- If user input is required to rectify the exception, throwing the exception back to a user interface is an appropriate solution.
Bloch, J. (2018). Effective Java Third Edition. Boston: Addison-Wesley.
Javamex. (2019, March 31). Exceptions: when to catch and when to throw? Retrieved from Javamex.com: https://www.javamex.com/tutorials/exceptions/exceptions_catch_vs_throw.shtml#
Lowe, D. (2017). Java All-In-One for dummies, 5th edition. Hoboken: John Wiley & Sons.
Murach, J. (2011). Java Programming, 4th edition. Fresno: Mike Murach & Associates.