Exception handling and its need
Java is a high-level programming language which runs on multiple operating systems. The java source code is written on any text editor or an IDE and saved as a program with .java extension. The Java compiler then compiles the source code into bytecode which is saved as a file with .class extension. The Java Virtual Machine then acts as an interpreter and converts it into a machine-readable format so that the code can be executed by the computer. If at any step, during this process, an unexpected event occurs that disrupts the normal flow of execution, the Java program will throw an exception. When we use methods to handle these exceptions so that the execution of the program gets completed and does not stop midway, that process is called exception handling. For a simple example, suppose you are travelling to work and your car breaks down, you will try to get a cab or share a ride to reach your workplace. A problem occurred that disrupted your normal morning routine. But you handled that by using alternative options available to you and reached your destination. Exception handling is important as it provides us with methods of handling an unexpected event in a program so that the program execution does not get disrupted. This post deals with understanding what these exceptions are and what methods Java provide to handle these exceptions.
Java Exception Hierarchy
Java has an inbuilt exception hierarchy that defines the classes available for these exceptions. The parent class of all the classes in Java is the Object class. Throwable is the parent class of Exception class and Error class. Inheritance is used to categorize different types of Exceptions. Throwable is the parent class of Java Exceptions hierarchy with two child classes, Exception and Error. Exceptions are further divided into Checked Exceptions and Runtime Exceptions.
Difference between Compile Time Exception and Runtime Exception
In simple words, a checked or compile time exception is one that is reported at the time of compilation of a java program. We usually see a red line under the code snippet. The exception has not yet occurred, but the compiler reports the possibility of such an exception occurring. Runtime exceptions are those that are not reported at the time of compiling the program. These occur when the program is executed. The following are the main differences between the two:
Compile Time Exception/Checked Exception
Runtime Exception/Unchecked Exception
These exceptions are reported and handled at the time of compiling the program.
These exceptions are not caught at the time of compiling the program.
The program will give a compilation error if a method throws a compilation exception.
The program is compiled without any error because the compiler is not able to check the exception at compilation.
In case of checked exception, the method must either handle the exception using try-catch block or must specify the exception using throws keyword.
During the time of compilation, the method is not forced by the compiler to declare any unchecked exceptions.
Checked Exceptions are direct subclasses of Exception class but do not inherit the Runtime Exception class.
Unchecked Exceptions are a direct subclass of Runtime Exception class.
Difference between exception and error
Now that we know where the Exception and Error classes stand in the exception hierarchy, let us understand the differences between the two:
Exception is caused by the way the syntax or logic of a program code.
Error occurs mainly because of lack of system resources. It is difficult to anticipate them and much more difficult to recover from them. For instance, hardware failure, JVM crash or out of memory error.
Exceptions are recoverable and can be handled by the programmer.
Errors are caused at a system level and usually treated by system administrators. So, they are not recoverable by the programmers.
Exceptions are of two types:
Errors are of one type:
Java Exception Handling Keywords
Java provides the following specific keywords for the purpose of handling various kinds of Exceptions:
try-catch block is used for exception handling in Java code. try is the start of the block. The try block is used to specify a code that needs to be tested for errors while it is being executed.
catch is at the end of the try-catch block to handle the exception if the code mentioned in the try block fails. There can be multiple catch blocks with a try block. The catch block requires a parameter of the type of exception (e).
The optional finally block is used with a try-catch block. The finally block will always get executed, whether an exception has occurred or not.
The throw keyword is used to throw exceptions to runtime to handle it.
The throws keyword is used to declare exceptions when we are throwing an exception in the method but not handling it. It is always declared in the method signature.
Methods to print the Exception
When an exception object is created, it has three main parts, name, description and stack trace. We can use the following methods to print the exception:
It is the most widely used method to print exception details which will print all the details of an Exception, its name, description and stack trace.
This will help in printing the name and description of the Exception but not its stack trace.
This will print only the description of the Exception, it will not print its name or stack trace.
Try Catch exception
In the following snippet of code, the try-catch block helps in executing the program, catches the ArithmeticException in the catch block and prints the output in all the three ways mentioned above.
The moment an exception occurs, the execution moves inside the catch block and ignores the rest of the statements in the try block after the exception has occurred.
If there is no exception in the program, the execution does not go inside the catch block.
Difference between final, finally and finalize keywords
Final is a keyword that can be used with variable, method and class. The value of final variable will become fixed. A final method cannot be overridden. A class cannot inherit the properties of a class declared final.
The finally() block is a method that is always executed whether an exception is handled or not. It is used to put cleanup code such as closing a file, closing unused resources. It follows the try catch block.
The finalize() method is used with objects. It is executed prior to the garbage collection method. The finalize method is also used to clean up objects or close resources but only after garbage collection.
The following are the main features of Throw keyword:
Java throw keyword is used to explicitly throw an exception.
Checked exception cannot be propagated using throw only.
Throw is followed by an instance.
Throw is used within the method.
You cannot throw multiple exceptions.
The following are the main features of Throws keyword:
Java throws keyword is used to declare an exception.
Checked exception can be propagated with throws.
Throws is followed by class.
Throws is used with the method signature.
We can declare multiple exceptions e.g. public void method()throws IOException,SQLException.
A NullPointerException is thrown when the program attempts to use an object reference that has null value. E.g., accessing a method from a null object or modifying a null object’s field.
Exceptions built in Java
The following are some of the important types of Exceptions which explain certain exceptional situations that occurred while executing the program.
ArithmeticException: This exception is thrown when an exceptional arithmetic condition has been established. For example, division by zero.
ArrayOutOfBoundsException: This is a runtime exception in Java that occurs when an array is accessed with an illegal index.
ClassNotFoundException: It is a checked exception in Java that occurs when JVM tries to load a particular class but does not find it in the classpath.
FileNotFoundException: This exception extends IOException and it means that the attempt to open a file by the given pathname has failed.
IOException: It occurs when an input-output operation failed or got interrupted.
InterruptedException: It is thrown when a thread is processing, waiting or sleeping and it is interrupted.
NoSuchFieldException: It is thrown when a class does not contain the field or variable specified.
NoSuchMethodException: It is thrown when accessing a method that is not found.
NullPointerException: It occurs due to a situation when an uninitialized object is accessed or modified.
NumberFormatException: It occurs when a method is unable to convert a string into a numeric format in a correct manner.
StringIndexOutOfBoundsException: It occurs when a method indicates that an index is either negative or greater than the size of the string.
IllegalArgumentException: It occurs when a method has been passed an illegal or inappropriate argument. It is an unchecked exception.
IllegalStateException: it occurs when a method has been called at an illegal or inappropriate time.
Exception handling is important because while running a program certain undesirable states or situations may occur. Handling these exceptions helps in running these programs without disrupting their normal flow and prevents the program or system from crashing. Exception handling also provides a means to separate the details of what to do when something out of the ordinary happens from the main logic of the program. That way the sanctity of the code and its primary logic is maintained while giving a chance to the user to modify and correctly execute the code.