Exception Handling is one of the most important feature which all the Java developers should know.
In this article we will learn
-
- What is an exception
- Types of Java Exceptions,
- Exception Hierarchy
- 5 Essential keywords in Java Exception Handling
- How to handle exceptions in Java with examples.
What is an exception?
An Exception is a unexpected interruption which occurs during the program execution and disrupts the execution of the program. Exception can occur on various situation such as
- Suppose while doing the file operations, if the required file is not found
- When the user keyed in some invalid data for processing
- When the resource allocated for the execution gets exhausted etc..
In case of the exception the system generated message will be displayed, which is not understandable to the user. The good thing about exception is that it can be handled by code and provide a useful message rather than the system generated message.
Types of Java Exceptions
Exception can be classified into 3 types
-
- Checked Exception / Compile Time exception
- Unchecked Exception / Runtime Exception
- Error
Checked Exception / Compile Time exception
The Checked Exception is an exception which is checked by the compiler during the compilation time and hence it is also called as Compile Time Exception. The Compile Time exception are the exception which a programmer can foresee and handle accordingly in the application.
The Compiler follows “Handle Or Declare Rule” for the checked exceptions, if a code throws compile time exception the compiler requires us to handle the exception in the code or declare the exception in the method using the throws keyword.
Throwable class and Exception class and its sub classes all put together is called as Checked Exception.
Some of the Checked exceptions are
- IOException
- SQLException
- FileNotFoundException
- ClassNotFoundException
- MalformedURLException
- InvocationTargetException
Let’s say if we are reading a file and we will be passing the path of the file to the constructor of the File class and if the file does not exist in the corresponding path then the code will throw FileNotFoundException. The compiler will prompt the programmer to either handle the exception or declare the exception
package com.javainterviewpoint; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; public class ReadFile { public static void main(String[] args) { File file = new File("D:\\temp.txt"); BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); String input; while ((input = bufferedReader.readLine()) != null) System.out.println(input); } }
The above will be showing the errors in the compile time itself
Exception in thread "main" java.lang.Error: Unresolved compilation problems: Unhandled exception type FileNotFoundException Unhandled exception type IOException at com.javainterviewpoint.ReadFile.main(ReadFile.java:13)
UnChecked Exception / Runtime exception
The Unchecked exceptions is also know Runtime Exception as it is not checked at compile-time since the compiler does not whether the programmer has handled this exception or not. The Runtime exceptions are usally caused by the mistake of the programmer rather than the environment.
Error and RuntimeException and all its Sub classes is known as Unchecked Exception
Some of the Unchecked Exceptions are
- ArithmeticException
- NullPointerException
- NumberFormatException
- ArrayIndexOutOfBoundsException
Let’s say if you are dividing an integer by zero then the code will be throwing ArithmeticException, it is the duty of a programmer to make sure the divisor should not be zero
package com.javainterviewpoint; public class Demo { public static void main(String[] args) { int a = 12; int b = 0; System.out.println(a/b); } }
The above code will throw ArithmeticException
Exception in thread "main" java.lang.ArithmeticException: / by zero at com.javainterviewpoint.Demo.main(Demo.java:9)
Error in Java
Errors indicate a serious and irrecoverable problem, which an application should not try to catch. Errors are usually out of control due to Hardware problems, such as Virtual Machine error, Memory Leaks etc.
Some of the Errors in java are
- AssertionError – This error will be thrown when the assertion has failed
- IOError – This error will be thrown when there is a serious I/O error has occured
- AnnotationFormatError – This error will be thrown when the annotation is malformed
- VirtualMachineError – This error will be thrown when the JVM is broken or runs out of memory
Exception Hierarchy
Java.lang.Throwable is the super class of all Exception and Error in Java. Exception class and Error class are the two sub class of Throwable class. Exceptions can occur during the Compile time and Runtime whereas the Errors can happen only during the Runtime.
Now let’s dive deeper into exceptions and see how it can be handled.
Exception Handling
Whenever an Exception has occurred and if it is not handled by the developer the programs gets terminated and the system generated error message will be shown to the user. Lets look into the below scenario where exception is not handled.
package com.javainterviewpoint; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class FileRead { public static void main(String[] args) { try (BufferedReader br = new BufferedReader(new FileReader("C:\\JIP\\test.txt"))) { String text; while ((text = br.readLine()) != null) System.out.println(text); } catch (IOException ie) { ie.printStackTrace(); } } }
Output:
java.io.FileNotFoundException: C:\JIP\test.txt (The system cannot find the file specified) at java.io.FileInputStream.open0(Native Method) at java.io.FileInputStream.open(FileInputStream.java:195) at java.io.FileInputStream.(FileInputStream.java:138) at java.io.FileInputStream.(FileInputStream.java:93) at java.io.FileReader.(FileReader.java:58) at com.javainterviewpoint.FileRead.main(FileRead.java:11)
The above message is not user friendly and the user will not be able to understand the issue and retry with the correct option. This is where exception handling comes in handy all we can do is catch the exception and return the message in simple English with what went wrong ? and how to proceed further etc..
Throwable class provides some of the super useful method which will be used to handle the exception
Methods | Description |
---|---|
public String getMessage() | This method returns the exception message string [only the name of the exception], If suppose we are dividing 1/0 then we will be getting “/ by zero” |
public String getLocalizedMessage() | This method also returns the exception message string [only the name of the exception] but in the local language of the user [French, Chinese, etc..].In order to make this work, the class you are calling getLocalizedMessage() on must have overridden the getLocalizedMessage() method, if it has not overridden the getLocalizedMessage() then the super class method will be called which by default just returns the result of getMessage(). |
public Throwable getCause() | This method returns the cause of the Throwable or null if the cause of the exception cannot be determined. All the printStackTrace() method will inturn call the getCause() method to get the cause of the Exception which has occured |
public Throwable initCause(Throwable cause) | This method is used to initialize the cause of the Throwable class, It is generally called within the constructor, or immediately after creating the throwable |
public String toString() | This method returns the short description of the Exception, the returned String will be concatenation of Name of the Exception Class followed by colon (:) and result of the getLocalizedMessage() method. Suppose we get DivideByZeroException then the toString() method will return something like this “java.lang.ArithmeticException: / by zero” |
public void printStackTrace() | This method prints the Throwable and the complete error stream which enables us to back trace the error cause. The first line will be the output of the toString() method and remaining lines will be the data previously recorded by the fillInStackTrace() method |
public Throwable fillInStackTrace() | This method fills the execution stack trace and the information about the state of the current thread |
public StackTraceElement[] getStackTrace() | This method returns the array of Stack trace elements which will be printed by the printStackTrace() method |
5 Essential keywords in Java Exception Handling
Java provides 5 essential keywords which will be used for Exception Handling, lets understand the core functionality of those keywords
- try
- catch
- finally
- throw
- throws
try:
- try block is the place where we will put the code which might raise an exception, suppose if we are trying to open a file and read the content of it and there is a possibility that the file may not be present in the corresponding location which can lead to an exception. We need to put these type of code where you foresee an exception possibility.
- The try block must be always followed by either catch block or finally block, the try block cannot exist separately, If not we will be getting compile time error – ” ‘try’ without ‘catch’, ‘finally’ or resource declarations”
- If both the catch and finally blocks are present it will not create any an issues
- Even if the code inside the try block is a single line we need to have the code enclosed within the curly braces ‘{ }’, if not we will getting a compile time error like ” ‘{‘ expected “.
catch:
- The catch block contains the code which handles the exception which is raised from its corresponding try block
- Lets take the above scenario where we read a file and if the file does not exist then in the catch block we will catch the exception and inform the user that the file is not present rather than presenting the user with the system generated error message
- The catch clause cannot exist separately, it has be always associated with the try block.
- The catch block takes one parameter which should be of type Throwable or any of the sub classes of it. This parameters hold the exception information which has occurred in the corresponding try block.
- The code inside the catch block should also be enclosed within the the curly braces ‘{ }’, if not we will getting a compile time error like ” ‘{‘ expected “.
finally:
- The finally block performs the clean up operations such closing the database connections, closing the files and resources which is opened.
- The finally clause would always be executed irrespective of whether the exceptions happened or not and whether exception is handled or not.
- This block will not get executed in a certain situation such as when the system got hung or the program crashed due to some fatal error or exiting the JVM using System.exit()
- The finally block also cannot exist separately, it has to be associated with a try block. Valid scenarios would be try – finally and try – catch – finally.
throw:
- The throw keyword is used to explicitly throw an exception, the exception can be either Checked or Unchecked. In real world mostly the throw keyword is used to throw the custom exception.
- The instance of the exception thrown should be of type Throwable or any of the sub classes of it.
- The program execution flow get stopped once the throw statement is executed, then the nearest try block will be checked to see if it has a matching catch block to catch the exception and so on. If no matching catch block is found then the program terminates displaying the system generated exception information.
- Say for example,we can catch ArrayIndexOutOfBoundsException and StringIndexOutOfBoundsException and in turn throw IndexOutOfBoundsException
throws:
- Whenever a method is capable of causing an exception and if it has not handled then it must declare the exceptions using the throws keyword, so that caller method is aware of the exceptions which might occurs and handle it using the appropriate catch block.
- Except the Error and RuntimeException or any of their sub classes, all the other exceptions which a method can throw must be declared using throws keyword.
How to handle exceptions in Java with examples
Lets put all together
Catching Exceptions using try catch
The try keyword specifies that the enclosed code has the potential to raise an exception. The catch block is placed after the try clause specifying the exception which will be caught. If a catch clause is not provided for a checked exception, the compiler will generate an error.
package com.javainterviewpoint; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class FileRead { public static void main(String[] args) { BufferedReader br = null; FileReader fr = null; try { fr = new FileReader("C:\\JIP\\test.txt"); br = new BufferedReader(fr); String text; while ((text = br.readLine()) != null) System.out.println(text); } catch (FileNotFoundException e) { e.printStackTrace(); } } }
In the above code, we are reading a file which will generate a compile time exception as there might be a situation where the file is not placed in the mentioned location. The try block will throw FileNotFoundException and since we have a corresponding catch block, the exception will be caught and the exception stack trace will be printed.
Catching Multiple Exceptions
There can be a situation where a particular code has the tendency to throw multiple exceptions. You want to catch each of the exceptions that may occur within a try block. There are two ways to handle this scenario
- Using Multiple catch block
- Catch Multiple Exception in a Single catch block
Let’s take a look into the above code, the FileReader will be throwing the FileNotFoundException and the BufferedReader’s readLine() method will be throwing IOException.
1. Using Multiple catch block
More than one catch clause can be specified in situations where multiple exceptions can occur within the same block. Each of the catch block can catch different exception and can be handled differently.
package com.javainterviewpoint; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class FileRead { public static void main(String[] args) { BufferedReader br = null; FileReader fr = null; try { fr = new FileReader("C:\\JIP\\test.txt"); br = new BufferedReader(fr); String text; while ((text = br.readLine()) != null) System.out.println(text); } catch (FileNotFoundException fe) { fe.printStackTrace(); } catch (IOException ie) { System.out.println("IOException has occured"); } } }
In the above code, we have added two catch clauses.
- The first one will be catching FileNotFoundException and printing the stack trace
- The second one will be catching IOException and print the message “IOException has occured”
2. Catch Multiple Exception in a Single catch block
If we need to catch multiple exception in a single catch block and handle the same way, then we can use the pipe symbol “|”, to separate the exceptions
package com.javainterviewpoint; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class FileRead { public static void main(String[] args) { BufferedReader br = null; FileReader fr = null; try { fr = new FileReader("C:\\JIP\\test.txt"); br = new BufferedReader(fr); System.out.println(1/0); String text; while ((text = br.readLine()) != null) System.out.println(text); } catch (IOException | ArithmeticException e ) { e.printStackTrace(); } } }
The above code catches the two exceptions IOExceptions and ArithmeticException and perform the same operation [print stack trace] for both the exceptions.
Catching All Exceptions
If suppose in the above code we caught only two exceptions IOExceptions and ArithmeticException, what will happen when some other exception has occurred say NullPointerException. Since we don’t have catch block for catching the NullPointerException, theabnormal program termination will happen
In order to avoid this situation all you need to is add one more catch with the base class of all exceptions [Exception or Throwable]. This catch block will catch all the exceptions as it is the super class of all exceptions.
The code can be rewritten like below
package com.javainterviewpoint; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class FileRead { public static void main(String[] args) { BufferedReader br = null; FileReader fr = null; try { fr = new FileReader("C:\\JIP\\test.txt"); br = new BufferedReader(fr); String text; while ((text = br.readLine()) != null) System.out.println(text); } catch (FileNotFoundException fe) { fe.printStackTrace(); } catch (IOException ie) { System.out.println("IOException has occured"); } catch (Exception e) { e.printStackTrace(); } } }
The first and second catch clause will catch FileNotFoundException and IOException respectively and the third catch block will catch all the other possible exceptions which can occur.
Closing Resources
We need to close all of resources that are acquired within a try/catch block after the block execution is completed. If the program does not close the acquired resources properly then the resource can be acquired indefinitely or could cause memory leaks or if the resource is limited then it might cause performance degradation.
We can close the acquired resources in two different ways
- Using finally block
- Using Automatic Resource Management (ARM) feature – try-with-resources block
1. Using finally block
The finally clause does the clean up work closing the resources which is opened in the try / catch clause. Code that is placed within the finally clause will always be executed irrespective of the exception. In the above code, we have opened the FileReader and BufferedReader which has to closed if we failed to properly close resources it will result in a resource leak
The code can be rewritten like below
package com.javainterviewpoint; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class FileRead { public static void main(String[] args) throws IOException { BufferedReader br = null; FileReader fr = null; try { fr = new FileReader("C:\\JIP\\test.txt"); br = new BufferedReader(fr); String text; while ((text = br.readLine()) != null) System.out.println(text); } catch (FileNotFoundException fe) { fe.printStackTrace(); } catch (IOException ie) { System.out.println("IOException has occured"); } catch (Exception e) { e.printStackTrace(); } finally { if (fr != null) fr.close(); if( br != null) br.close(); } } }
We are the closing the opened resource such as FileReader and BufferedReader in the finally block
2. Using Automatic Resource Management (ARM) feature | try-with-resources block
This feature was introduced in Java 7, all you need to do is that open the resource which is required for the code should be declared in the try-with-resources block and that’s it.
Any object that implements java.lang.AutoCloseable interface will be automatically closed once after the execution of the try block is completed or in case of an exception.
package com.javainterviewpoint; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class FileRead { public static void main(String[] args) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader("C:\\JIP\\test.txt"))) { String text; while ((text = br.readLine()) != null) System.out.println(text); } catch (FileNotFoundException fe) { fe.printStackTrace(); } catch (IOException ie) { System.out.println("IOException has occured"); } catch (Exception e) { e.printStackTrace(); } } }
In the above code we have opened the resources like BufferedReader and FileReader in the try-with-resources block which will be closed once after the program execution is complete or in case of a exception. There is no need for finally here.
Throwing Exceptions – Throw keyword
The throw keyword allows you to explicitly generate exceptional condition by throwing a specified Throwable (exception) object. This statement stops program execution and passes it to the nearest containing catch statement that can handle the specified exception object.
package com.javainterviewpoint; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class FileRead { public static void main(String[] args) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader("C:\\JIP\\test.txt"))) { String text; while ((text = br.readLine()) != null) System.out.println(text); } catch (FileNotFoundException fe) { throw new FileNotFoundException("File not present"); } catch (IOException ie) { System.out.println("IOException has occured"); } catch (Exception e) { e.printStackTrace(); } } }
Whenever FileNotFoundException occurs we will be catching the exception and throwing the FileNotFoundException with the string “File not present”
I hope you found this post informative. Happy Learning!! 🙂
Leave a Reply