Java Exceptions

Jeff Li
4 min readJul 29, 2021

As Java developers, we probably need to work together with our old friend, Exception, in our daily life. However, we might know this old friend for years but, sometimes, he would like to stay mysterious. Like, “where did he come from?”, “Does he has siblings?”, and “which one should I pick?”. So it is time to know him better.

What are Java Exceptions?

When a program violates the semantic constraints of the Java programming language, the Java Virtual Machine signals this error to the program as an exception.(from Oracle Official Doc)

Simply put, the Exception is an exceptional event that fails to behave as we expect.

Why are Java Exceptions introduced by Java designers?

When it comes to handling exceptional events, different programming languages have their own different strategies. For example, when the program is trying to access the data through a null reference, some programming language will run unpredictably; other programming languages may just terminate the program simply or fail silently.

These strategies may be reasonable in their specific platforms but harm portability and robustness, which are the design goals of Java.

Portability: the program can easily run on other platforms without much rework. Imagine that the exceptions are handled in an unpredictable way(something like platform-specific stuff, different platforms react in different ways). We probably need the effort to modify our code for different platforms.

Robustness: the ability to cope with unexpected events. The program should be able to recover from some exceptional events that we want to deal with. However, just terminating the program or failing silently may not be a good way to enhance robustness.

In old fashion, the API tends to return some funny values to tell its caller there is an exception happened. Like, in C, lots of APIs, where -1 is not expected to be valid, just return -1 for error cases. The drawback of this strategy is that developers can ignore it easily without awareness and sometimes it is not that easy to find such funny value to represent an error case.

Exceptions Hierarchy

Throwable and all its subclasses are, collectively, the exception classes.

Java Exceptions Class Hierarchy

Throwable: All exceptions’ superclass

Exception: the superclass of all the recoverable exceptions. Like, IOException, SQLException, and etc. As you can see, RuntimeException is also the subclass of Exception. However, usually, the program should not try to handle and recover from RuntimeException, though it is still recoverable, cos they are generally programming errors, like NullpointerException. So developers should fix these RuntimeExceptions manually.

Error: the superclass of all the exceptions that are not recoverable. Like, VirtualMachineError, OutOfMemoryError, LinkageError, and etc. Generally speaking, our programs won’t try to handle these errors.

The benefit that separates Error from Exception in Class Hierarchy is that we can use the idiom try{..} catch(Exception e){..} without catching these unrecoverable Errors.

Checked vs Unchecked Exceptions

There is another concept associated with Exceptions based on whether it requires a compiling-time check.

In the class diagram above, all exceptions colored by green are Unchecked Exceptions, which means it is not forced to add handlers for them. Error is unchecked cos these exceptions are kind of tricky to handle. In some sense, the program can't recover from Error easily. RuntimeException is unchecked cos, on the one hand, they are programming errors and it won’t help much to the correctness of the program by handling these errors. The developers are responsible to fix these problems manually. On the other hand, it is difficult for Java Compiler to prove the existence of RuntimeException, like NullPointerExcetpion.

The rest of the exceptions are Checked Exceptions and explicit handlers are required in your code. Otherwise, a compile error occurs.

Sometimes, it is kind of confusing about the design preference between Checked Exception and Unchecked Exception. When clarifying this topic, we need to stand on the view of an API designer.

When callers are calling your API in a wrong way, like the parameter is not valid or index is out of the boundary, the API should throw Unchecked Exceptions to tell developers there is a programming error in their code. And then developers can debug and fix the error by themselves.

When callers are calling your API correctly and there are still some unavoidable exceptions that happen, your API should throw Checked Exception to let developers know there is something wrong and the developers can add handlers to recover. Like, in IO Operations, even though everything is validated by its callers, there is a possibility that the file is corrupted by others before being read. So the callers should be aware of that case and handle them based on their requirements.

Summary

Someone may not like the style of Java Exceptions. Checked Exceptions are sometimes kind of annoying, which break your code structures and cause boilerplate. Anyway, we need to think over the design when using Java Exceptions.

--

--