Every programmer wants to write a flawless program. That is, a program that runs without any hitch or glitch.
Well, if wishes were horses, beggars would ride. Beyond all the wishes of a programmer, sometimes unforeseen circumstances happen.
These unforeseen circumstances are generally categorized as ”exceptions” in Java. Exceptions interfere with the smooth running of our code and terminate the program if not handled. Handling exceptions involves writing another set of code to manage these exceptions when they happen.
There are two classes of exceptions, those we can’t do anything about and those we can. For the second class, handling the exceptions properly is important, since we don’t want our code to terminate because of an exception.
Exceptions occur when our code runs in unexpected ways (which is why exceptions can be considered a kind of bug). These unexpected ways could be dividing a number by zero, trying to access an array at an index that does not exist, or trying to access an object that does not exist. All these ways results in exceptional code, code that does not follow the normal path or process the program designed.
When an exception occurs, a description is reported to the user to explain what caused the unexceptional code. The act of reporting this exception is called throwing an exception.
Exception handling is an integral part of Java; every Java developer needs to understand how to handle exceptions so that they can write clean, elegant code.
A car running on a bad fuel emits smoke so that we know something is wrong—an exception thrown in a Java Program is the equivalent to that smoke. When an exception happens in a Java program, it needs to be reported to the user of the system so that the user understands exactly what went wrong. By reporting this exception to the user, we are throwing an exception.
The programmer can cause an exception to be thrown or the Java language throws the exception. The programmer can cause an exception to be thrown when the user of the program performs some operations that have been clearly started as illegal or incorrect in the program. Also, the Java language can throw some exceptions if the input to the program violates some basic arithmetic or programming principles like dividing a number by zero and if the environment in which the program is running develops some issues like running out of memory.
So when a Java program throws an exception, what happens? An object of any of the Throwable subclass is created that explains the nature of the exception, depending on its type. For example, an ArithmeticException object can be thrown, which shows that an error in arithmetic occurred.
Any exception that can be thrown from a Java Program is considered to be an object of the Throwable class, which is divided into two subclasses: the Exception class and the Error class.
Exceptions that the programmer cannot handle are in the Error class. Exceptions that you can fix are in the Exception class.
Some exceptions are like natural disasters—they happen, and you just have to accept their occurrence. Exceptions that fall into the Error class are things you can’t fix. They also just happen and you have to accept their occurrence.
The Error class exceptions are normally used to show that something is wrong with the environment in which your code is running. These types of problems might include lack of memory—a case of a paucity of memory is not something you write code to handle so you cannot simply just deal with it. These exceptions simply terminate your program.
Error class exceptions are fixed by restarting the program, but only after the problem in the environment that caused the program to terminate has been resolved. In our example, a fix to the error might include manually recovering space for the execution of the program.
Just know that Java does not fix Error class exceptions; the owner of the program must do something after the code terminates to ensure that the program works again.
Exceptions that can be handled when they occur under the Exception class. The Java programming language has a myriad of exceptions that can be handled under the subclass RuntimeException.
These exceptions include the Division by Zero exception, which happens when you try to divide a number by zero.
Exceptions of the Exception Class are able to be handled because they signify that some problems occurred inside the code, not in the environment in which your code is run.
You can avoid such exceptions by writing code that ensures that they do not occur in the first place, and if they do occur, you write code to ensure that the exceptions do not terminate your program execution. To handle exceptions, they are placed in a try block, which we will get to shortly.
The basic difference between the Error Class and the Exception Class is that the Error class would cause the program to terminate and it cannot be handled, but the Exception Class can be made to not cause the program to terminate if the exception is properly handled.
Important Keywords Involving Exceptions
Exception handling in Java is made possible through the use of some keywords like try, catch, throw, throws, and finally. These keywords are used to manage how exceptions are thrown and handled.
Any piece of code that might cause an exception to be thrown is written in a try block. Code that might throw an exception usually deal with input values, which are not guaranteed to always be the way the programmer wants.
Imagine a baby that tries to walk. You simply put your hands around the baby to ensure that the baby does not fall and injure themselves. In the same way, the try block is used to surround code that might throw an exception while running.
A try block is followed immediately by a catch block or a finally block or both.
A catch block does exactly what its name says: it catches an exception thrown in the try block. Since a number of exceptions can be thrown, the catch block must specify the class of exception it is handling.
Beyond a catch block, there is the finally block, which simply works when the try block is done. So, the finally block waits for the try block to execute. Note that a try block can be followed by a catch block or a finally block or a combination of both. If the try block has a catch block, finally runs after the catch, otherwise the finally block runs immediately after the try block.
So imagine the finally block as the final resort for a try block. The finally block is normally used for handling resources that might not have been properly utilized by the try block.
A method, or a piece of code that performs a specific function in Java, can throw a type of exception by using the throws keyword in the method heading.
Exceptions in the Error or RuntimeException and their subclasses need not be included in the throws statement. They are classified as Unchecked Exceptions, which are exceptions that should be prevented in any way possible and must not be consciously allowed to occur.
The number of Unchecked Exceptions that can occur in a program are so enormous that we cannot throw all the Unchecked Exceptions in a method. It would cause the method to lose its clarity, so Java assumes that a programmer running a program does not intentionally throw these type of exceptions.
Every method is already liable of throwing unchecked exceptions when something goes wrong, so no need to add unchecked exceptions in the throws statement.
The throw keyword is used to specifically throw an exception in a method. It simply serves the normal use as in the verb throw: it throws an object of the Throwable Class. You cannot throw objects that are not in the Throwable Class or any of its subclasses. Be careful to not throw Unchecked Exceptions with the throw keyword. Use the throw keyword for throwing Checked Exceptions.
Why Handle Exceptions?
Because every program we write would at one point or another throw an exception, it is important to understand how to handle them so that an exception does not always terminate our program every time it happens in our code.
Knowing the difference between exceptions that fall into the Error Class or the Exception Class can help you determine whether or not you can fix the problem.
When you’re writing code to handle exceptions, make sure you understand and correctly use the try, catch, and finally blocks, and remember to do your best to prevent Unchecked Exceptions from being thrown.
Learning how to handle exceptions before they happen will help you write clean, elegant code.