Good day, guys! I’m back with an essential piece about something you might have already encountered. The focus of today’s article is on Exception Handling in Java. First, let’s get a firm grasp on the concept of exception handling.
What are Exceptions?
Java Docs describes an exception like this.
An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions.Java Documentation
What are Errors and Exceptions?
Java’s Throwable class has two subclasses called Error and Exception. Refer to the following graph to understand the full hierarchy.
What does it mean to throw an exception?
When a method encounters an error, it creates an exception object and passes it to the runtime system. This exception object contains all of the important details about the issue that occurred. Throwing an exception is the process of passing the exception object to the runtime system.
Why should we handle exceptions?
To keep the application’s usual flow, we need to manage exceptions. The rest of the code will not be performed if an exception occurs. That should not happen in our applications. So, even if exceptions arise, we must handle them and make the code run properly.
Can we only catch Exceptions?
Errors such as OutOfMemoryError or IOError can also be caught. However, for a newbie, the best suggestion is to focus on handling exceptions because errors usually indicate major issues that a reasonable program should not strive to handle.
Check out this stackoverflow answer to see how we can catch the OutOfMemoryError in Java.
Types of Exceptions in Java
There are two exception types.
- Checked Exceptions
- Unchecked Exceptions
Exceptions that are checked at compile time are known as checked exceptions. If you look into the hierarchy again, the subclasses that are on the same level of RunTimeException class are checked exceptions.
Unchecked Exceptions are the list of exceptions that are checked at runtime. In the hierarchy, these are the subclasses of the RunTimeException class.
Here’s an example of code where we’re attempting to divide 100 by 0 and getting an exception.
Here is what happens when we execute the above code snippet.
If you look closely, you’ll notice that the code after the exception hasn’t been executed. Let’s handle the exception in the following code.
Let’s see what happens when we execute this code block.
As you can see, the whole code has been executed properly since the exceptions were handled.
Keywords Used in Exception Handling
There are mainly 5 keywords that we use when handling exceptions in Java
Take a look at the following code snippet
You should probably understand all the keywords and the usage from the above code snippet. Don’t be alarmed if you did not understand the CustomException part. I will be explaining how we can create our own exceptions.
Multiple Catch Blocks
We can have multiple catch blocks for a single try block. We can execute different code blocks according the occurred exception.
In the above code snippet, I have created two catch blocks to catch two different exceptions. Let’s see how the code gets executed.
You can see that since an ArithmeticException occurs, the relevant catch block gets executed. Let’s comment out and see what happens.
Now, the exception that is being occurred is IndexOutOfBoundsException and the relevant catch block is getting executed.
Nested Try-Catch Blocks
Nested try-catch blocks are when we have a try-catch block inside another try block.
Using nested try-catch blocks are a bit debatable. Some programmers argue that it is not a good coding practice. Anyway, I don’t see anything inherently wrong with nested try-catch blocks. If you are interested, do some research before using them.
What is Exception Propagation?
When an exception occurs inside a method, the runtime system searches for a exception handler to handler the exception going through the call stack. The call stack is the ordered list of method that were called to get to the method where the exception occurred.
Take a look at the following example.
Here the call stack has the following order.
main -> method1 -> method2 -> method3
The exception is occurred inside method3. So, it checks if there is an exception handler in that method. Since there are no exception handlers in method3, it goes back to the method2 to check if there is an exception handler there. It goes searching in the call stack in reverse order until it finds an exception handler that can handle the occurred exception. If it fails to do so, the program will stop working.
We can clearly see how it searches inside each method in reverse order, when we take a look at the error that is logged when we do not add an exception handler in the code.
Method Overriding with Exception Handling
Take a look at the following code.
This code snippet throws the following error.
We are throwing a RuntimeException from the super class and trying to throw an IOException from the subclass. This is not allowed. We can either throw the RunTimeException or a subclass of that class from the subclass method. We can’t throw an exception that is on the same level or higher than the RunTimeException.
Here is the corrected code.
Creating Custom Exceptions
We can create our own exceptions in Java and throw them whenever we want. To create our own exception, we just need to create a java class and extend Java’s Exception class.
Well, I guess that is pretty much all you need to get started with handling exceptions in Java. Try these concepts out in your Java projects.
Thank you for reading the article. I hope you learned something valuable from today’s article. If you did, please drop a like, follow the blog and share the article with your programming buddy. Until next time, stay safe ✌😷