Most of the answers on this forum have been talking about the Exception hierarchy and the Java compiler not catching them but I would try to answer this more from the design perspective and why perhaps things were designed like this.
Basically when you call a function(or write some code) an exception can be thrown out of it based on three different situations:
Based on an unavoidable condition like unavailability of network or some expected file missing on the file system.
Based on an avoidable but known condition like Integer.parseInt(String)
can throw NumberFormatException
if the caller passes a unconvertible string like "Hello"
, but the caller may ensure proper validations in place before passing in any string to the function and completely do away with the possibility of generating the exception. A common use case could be validating the form field age
on a web page before passing it to deeper layers that make the conversion.
An unknown or unexpected condition Any time some line of code can throw an exception in your code because there was some mistake that you did and didn't observe the error condition until it blasted off in production, generally happens with NullPointer Reference
, IndexOutOfBounds
etc, which if observed would possibly fall in category 2.
Exceptions of category 1 are generally designed as Checked Exceptions
because it needs to enforce the check for unavoidable error conditions, and to enforce their fallbacks. For examples IOException is checked exception, because in case you are opening a file, there can be a lot many things that may go wrong(like file may be deleted, permissions etc.)and pre validating all of them can be very cumbersome.
Exceptions of the 2nd type are generally modeled as Unchecked Exceptions
because you might have your pre validation in place and it might be irritating to be forced to use try and catch for situations that you have already have taken care of.
Exceptions of the 3rd type need not be even worried about generally because you cannot put error handling in each and every statement of application code that can unexpectedly come up. But sometimes you can place a global handler, somewhere quite up in the call stack from where almost all the application code gets executed and handle it in a generic manner so that your application does not crash due to an unexpected error.
For example, if you're running a web application you can configure your Servlet Container to send out a generic 500 Internal Server Error
for any unhandled error in your application. Or, if you're running a standalone Java application you can keep the contents of your main method
in a try catch
block to prevent crashing the application.