We may not have the course you’re looking for. If you enquire or give us a call on +358 942454206 and speak to our training experts, we may still be able to help with your training requirements.
Training Outcomes Within Your Budget!
We ensure quality, budget-alignment, and timely delivery by our expert instructors.
In the realm of Programming, exceptions are like unexpected plot twists—they disrupt the normal flow of your code. But fear not! Java provides a powerful mechanism to handle these runtime errors gracefully. Whether it’s a ClassNotFoundException, IOException, or SQLException, we’ve got you covered.
This is where Exception Handling in Java comes to the fore as a saviour. It is an elaborate process in which runtime errors are handled effectively resulting in seamless execution. According to Oracle, Java reigns supreme when it comes to developing dynamic services like microservices.
So, buckle up as we explore the ins and outs of Exception Handling in Java, unravel the types of exceptions, and learn how to keep your Java applications sailing smoothly!
Table of Contents
1) What is an Exception in Java?
2) Why do Exceptions occur?
3) What is Exception Handling?
4) Keywords in Java Exception Handling
5) Useful Methods of Exception classes
6) Java Exception Hierarchy explained
7) Types of Exceptions
8) Difference Between Checked and Unchecked Exceptions
9) Best Practices for Exception Handling in Java
10) Common Exceptions and Errors
11) Conclusion
What is an Exception in Java?
In Java, an Exception is an event or condition that disrupts the normal flow of program execution. It represents an error, typically arising during runtime, that can be due to various factors such as invalid input, file not found, or network issues. Exceptions are categorised into two types: Checked Exceptions (compile-time enforced) and Unchecked Exceptions (runtime exceptions).
When an exceptional condition occurs, Java creates an Exception object containing information about the error and searches for a suitable Exception handler. Developers can use try-catch blocks to handle Exceptions, ensuring the program gracefully responds to errors. Additionally, Java's Exception hierarchy, with the base class Throwable, allows for a structured approach to handling different types of Exceptions, promoting code reliability and robust error management.
Why do Expectations occur?
Exceptions are of different types, each occurring for a different reason. The types of Exceptions in Java will be discussed later in the blog. For now, let's run through some of the major reasons why Exceptions occur and when Exception Handling comes into play.
a) Invalid input by the user
b) Physical limitations
c) Device failure
d) Error in coding
e) Weak or no network connection
f) Opening an unavailable file
What is Exception Handling?
As explained before, Exception Handling in Java is one of the most powerful and effective methods to handle runtime errors. Handling Exceptions helps ensure the smooth and regular flow of the program. The most common runtime errors include IOException, ClassNotFoundException, SQLException, and more.
Using Exception Handling is an extremely useful method and there are various reasons for that. Some of the benefits of Exception Handling include error propagation, meaningful error reporting, and identifying error types. Additionally, handling Exceptions help in completing program execution and in the easy identification of Program Code and Error-Handling Code.
Improve your understanding of JavaScript by signing up for our JavaScript for Beginners Course now!
Keywords in Java Exception Handling
Java uses specific terminologies exclusively, which is essential to understand. Your understanding of the Exception hierarchy and Handling will depend on these words. Thus, here is a list of keywords in Java Exception Handling:
a) try: "try" is associated with a block where the Exception codes must be placed. One of the characteristics of “try” is that the block cannot be used alone. In Java, the “try” block is always followed by a "catch" block or a "finally" block.
b) catch: "catch" refers to the block where the Exception is handled. Similar to “try”, the “catch” block also cannot be used alone. The “try” block must precede the "catch" block, or the finally block must succeed.
c) finally: The "finally" block is where the necessary code of the program is executed. A characteristic of the “finally” block is that it executes whether Exceptions are handled.
d) throw: As the name suggests, the "throw" keyword simply means to throw an Exception.
e) throws: "throws" is used to declare Exceptions. It's used alongside method signature all the time. “throws” help specify the possibility of an Exception in the method, and it doesn't throw an Exception.
f) Errors: Irreparable conditions like memory leaks, errors in stack overflow, infinite recursion, and more are represented by errors. Even the Java Virtual Machine (JVM) running out of memory falls under the abovementioned conditions.
Most of the time, the programmer cannot control the errors. We should not handle errors and should not detect them, whereas exceptions must be tried.
Useful Methods of Exception Classes
Java Exception and its subclasses lack specific methods, with all methods defined in the base class, Throwable. These Exception classes pinpoint different Exception scenarios for easy identification and handling. The Throwable class implements the Serialisable interface for interoperability.
Key methods of the Throwable class include:
a) public String getMessage(): Returns the throwable message, set during Exception creation.
b) public String getLocalizedMessage(): Subclasses can override to provide locale-specific messages, utilising the getMessage() method.
c) public synchronised Throwable getCause(): Returns the Exception cause or null if unknown.
d) public String toString(): Returns Throwable information in String format, including class name and localised message.
e) public void printStackTrace(): Prints stack trace information to the standard error stream; writing to a file or stream with PrintStream or PrintWriter as arguments is overloaded.
Learn to make desktop applications and understand concepts of Swing. Sign up for our Java Swing Development Training now!
Java Exception Hierarchy Explained
The Java Exception Hierarchy consists of classes and sub-classes that explain the position held by them. The base class of the Exception hierarchy is known as "Throwable". All the Exception types and error types act as subclasses as they fall under “Throwable” class.
The Exception class is used for the Exceptional conditions that Java user programs must never fail to catch. Examples of this type of Exception would be ArithmeticException or NullPointerException.
The Error class or branch is used to show errors related to the Java Run-time Environment (JRE). The Java run-time system uses errors, and the StackOverflowError can represent an example of this kind of error.
Types of Exceptions
Exceptions are mainly of two types – User-defined Exception and Built-in Exception. Built-in Exceptions are further divided into Check Exceptions and Unchecked Exceptions. It is important to understand the difference between those two.
a) Checked Exceptions: Checked Exceptions are checked during compile-time by computers. Thus, they are also known as compile-time Exceptions. Examples of checked Exceptions include IOException, SQLException, etc.
b) Unchecked Exceptions: As the name suggests, unchecked Exceptions act as the antonym for checked Exceptions. Unchecked Exceptions are not checked during compile-time.
For instance, if a program throws an unchecked Exception, regardless of whether you handle or declare it, it doesn't give out a compilation error. Examples include ArithmeticException, ArrayIndexOutOfBoundsException, etc.
Java Try-catch Block
As mentioned above, the Java “try” block contains the code that could potentially throw an Exception, which must be used in a method. One of the points to remember is to not keep the code in a “try” block that will not throw an Exception. If an Exception occurs in the “try” block, the rest of the block code won't execute.
The syntax of Java try-catch is:
Try
{
//code that may throw an Exception
}catch(Exception_class_Name ref){}
The following is an example of Exception Handling using Java try-catch:
public class ExceptionHandlingExample
{
public static void main(String[] args)
{
try
{
int numerator = 10;
int denominator = 0;
int result = numerator / denominator;
System.out.println("Result: " + result);
}
catch (ArithmeticException e)
{
System.out.println("Error: Division by zero.");
}
}
}
Here, the objective is to divide the numerator by the denominator. Since the denominator is zero, it will throw an 'ArithmeticException'. The "catch” block will catch the Exception and print the error message "Error: Division by zero." to the console.
Output:
Error: Division by zero.
Java Multiple Catch
More than one “catch” block can succeed a “try” block, and every individual catch block must have unique Exception handlers. Thus, Java multi-catch block is used to perform different tasks upon detection of different Exceptions.
Syntax for Java multi-catch:
try
{
// code that may throw an Exception
}
catch (ExceptionType1 ExceptionVariable1)
{
// code to handle the Exception of type ExceptionType1
}
catch (ExceptionType2 ExceptionVariable2)
{
// code to handle the Exception of type ExceptionType2
}
catch (ExceptionType3 ExceptionVariable3)
{
// code to handle the Exception of type ExceptionType3
}
finally {
// code that will be executed whether an Exception was thrown or not
}
When an Exception is thrown in the “try” block, Java will check each catch block to see if it can handle it. The first “catch” block whose Exception type matches the thrown Exception will be executed, and subsequent catch blocks will be skipped.
Example of Java Exception Handling using Java multiple-catch
public class ExceptionHandlingExample
{
public static void main(String[] args)
{
int[] nums = {1, 2, 3, 4, 5};
try
{
System.out.println(nums[6]);
// the above line will throw an ArrayIndexOutOfBoundsException
String str = null;
System.out.println(str.length());
// the above line will throw a NullPointerException
}
catch (ArrayIndexOutOfBoundsException e)
{
System.out.println("Caught ArrayIndexOutOfBoundsException: " + e.getMessage());
}
catch (NullPointerException e)
{
System.out.println("Caught NullPointerException: " + e.getMessage());
}
catch (Exception e)
{
System.out.println("Caught Exception: " + e.getMessage()); }
finally
{
System.out.println("Finally block executed.");
}
}
}
In the above code, we create an integer array called 'nums' with five elements. In the “try” block, we attempt to print the element's value at index 6, which is outside the array's bounds and will throw an 'ArrayIndexOutOfBoundsException'. We also attempt to call the 'length' method on a null string, which will throw a 'NullPointerException'.
We use multiple catch blocks to handle these Exceptions separately. The first “catch” block catches ArrayIndexOutOfBoundsException and prints an error message. The second catch block catches NullPointerException and prints another error message. We also include a third “catch” block that catches any other Exceptions that may be thrown.
Output:
Caught ArrayIndexOutOfBoundsException: 6
Finally block executed.
Since an Exception was thrown in the first try block, the program jumps to the appropriate catch block to handle it. The finally block was also executed afterwards.
Java Nested Try Block
The Java nested try block is when a “try” block can be used inside another “try” block. Sometimes, a block part could cause an error, and the block itself could cause another error. In such cases, the nested try block is used as the Exception handlers need to be nested.
Syntax of Java nested try:
Try
{
// Outer try block
try {
// Inner try block
// Some code that might throw an Exception
} catch (Exception e) {
// Catch any Exception thrown in the inner try block
}
} catch (Exception e) {
// Catch any Exception thrown in the outer try block
}
Example of Exception Handling using Java nested try:
public class NestedTryExample {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5};
try {
// Outer try block
for (int i = 0; i <= arr.length; i++) {
try {
// Inner try block
System.out.println(arr[i]);
} catch (ArrayIndexOutOfBoundsException e) {
// Inner catch block
System.out.println("Inner catch block: " + e);
}
}
} catch (Exception e) {
// Outer catch block
System.out.println("Outer catch block: " + e);
}
}
}
The first five lines of output correspond to the successful iteration of the for loop, printing out the values of the elements in the 'arr' array. On the 6th iteration of the for loop, we attempt to access the 6th element of the arr array, which does not exist, and this triggers an 'ArrayIndexOutOfBoundsException'.
The inner catch block catches the Exception, which prints out an error message: "Inner catch block: java.lang.ArrayIndexOutOfBoundsException: 5". Since the Exception is caught within the inner “try” block, the outer catch block is not triggered. The for loop completes, and the program ends.
Output:
1
2
3
4
5
Inner catch block: java.lang.ArrayIndexOutOfBoundsException: 5
Outer catch block: java.lang.ArrayIndexOutOfBoundsException: 5
Learn about the fundamentals of Java and programming with it. Sign up for our Java Programming Course now!
Java Finally Block
The Java “finally” block is used for the execution of important codes. One of its characteristics is that it's always executed regardless of whether an Exception is handled. This implied that it encompasses all the statements required to be printed, whether the Exception occurs.
Syntax for Java “finally” block:
try
{
// Some code that might throw an Exception
} catch (ExceptionType1 e1)
{
// ExceptionType1 handler
} catch (ExceptionType2 e2)
{
// ExceptionType2 handler
} finally
{
// Code to be executed regardless of whether an Exception was thrown or not
}
Example of Exception Handling using Java finally block:
public class Example
{
public static void main(String[] args)
{
try
{
int x = 10 / 0;
} catch (ArithmeticException e)
{
System.out.println("An error occurred: " + e.getMessage());
} finally
{
System.out.println("The finally block is always executed.");
}
}
}
In this example, we're trying to divide the integer ‘10’ by ‘0’, which is not allowed in Java and will result in an ‘ArithmeticException’. We catch the Exception and print an error message. We also have a ”finally” block that prints a message indicating that it's always executed, regardless of whether an Exception was thrown or not.
Output:
An error occurred: / by zero
The finally block is always executed.
Here, an 'ArithmeticException' is thrown and caught, and an error message is printed to the console. The 'finally' block is executed, and its message is printed to the console.
Java Throw Keyword
The Java “throw” keyword is used to throw an Exception explicitly, and the Exception object to be thrown is specified and has a message that describes the error. The Java “throw” keyword can throw both checked Exceptions and unchecked Exceptions.
Syntax of Java throw keyword:
throw throwable_object;
The “throw” keyword explicitly throws an Exception or error in Java. It can be used anywhere in a method, but it's typically used inside "try” blocks to handle Exceptions that the code can't handle in the "try” block.
Example of Exception Handling with Java throw keyword:
public class Example
{
public static void main(String[] args)
{
Try
{
int x = divide(10, 0);
}
catch (ArithmeticException e)
{
System.out.println("An error occurred: " + e.getMessage());
}
}
public static int divide(int a, int b)
{
if (b == 0)
{
throw new ArithmeticException("Division by zero is not allowed.");
}
return a / b;
}
}
In this example, we're trying to divide the integer '10' by '0', which is not allowed and will result in an 'ArithmeticException'. However, instead of using the / operator to perform the division, we've created a custom 'divide' method that checks whether the second argument is '0'. If it is, we throw an ArithmeticException with a custom error message.
We call the 'main' method the divide method with arguments' 10' and '0'. Since '0' is not allowed as the divisor, the divide method throws an Arithmetic Exception. We catch the exception in the 'catch' block and print an error message on the console.
Output:
An error occurred: Division by zero is not allowed.
Difference between Checked and Unchecked Exceptions
In Java, Exceptions are classified into two main types: Checked Exceptions and Unchecked Exceptions.
Feature |
Checked Exceptions |
Unchecked Exceptions |
Compilation requirement |
Must be handled (try-catch or 'throws' clause) |
No mandatory handling, left to developer discretion |
Time of checking |
Compile-time |
Runtime |
Examples |
IOException, SQLException |
NullPointerException, ArrayIndexOutOfBoundsException |
Nature |
External factors (I/O, network) |
Logical errors in the program |
Enforcement by compiler |
Enforced by the compiler |
Not enforced by the compiler |
Handling |
Explicit handling required |
Optional handling, recommended for stability |
Flexibility |
Less flexibility due to mandatory handling |
More flexibility, but demands rigorous testing |
Typical use cases |
Network operations, file I/O |
Array access, null references |
Checked Exceptions at compile-time require the programmer to handle them explicitly. This can be done by enclosing the code that may throw the Exception in a try-catch block or by declaring the Exception in the method signature using the 'throws' clause.
Checked Exceptions typically represent external factors beyond the program's control, such as file I/O issues, network problems, or database errors. Handling them ensures a more robust and fault-tolerant program, emphasising the importance of addressing potential issues that may arise during the execution of the code.
In contrast, Java's Unchecked Exceptions do not mandate explicit handling by the programmer. These Exceptions often result from logical errors in the program, such as attempting to access an array index that doesn't exist (ArrayIndexOutOfBoundsException) or dereferencing a null object (NullPointerException). Unchecked Exceptions are not checked by the compiler at compile-time, offering more flexibility to developers.
However, this freedom comes with the responsibility of thorough testing and code review to catch and rectify logical errors during development. While Unchecked Exceptions provide more leniency, it is crucial to adopt coding practices and testing methodologies that minimise these runtime issues, ensuring the reliability and stability of the software.
Best Practices for Exception Handling in Java
Exception handling can be a challenge. So here are some best practices to consider during Exception handling in Java:
a) Use Specific Exceptions: The base classes in the Java Exception hierarchy offer limited information, which is why Java includes numerous specific exception classes like “IOException” and its subclasses “FileNotFoundException" and "EOFException". Always throw and catch specific exceptions to clearly indicate the root cause, simplifying debugging and enabling client applications to handle exceptions appropriately.
b) Throw Early or Fail-Fast: Aim to throw exceptions as early as possible. For instance, in a "processFile()" method, passing a “null” argument should immediately result in an exception. This approach ensures errors are caught and addressed promptly
c) Catch Late: Since Java enforces either handling the checked Exception or declaring it in the method signature, developers often tend to “catch” the Exception and log the error. However, this practice needs to be avoided because the caller program doesn’t receive any notification about the exception. You should “catch” exceptions only when you can handle them appropriately.
d) Closing Resources: Since exceptions stop the processing of the program, you should use Java 7 “try-with-resources" enhancement to let java runtime close it.
e) Logging Exceptions: You must always log exception messages and provide a clear message when throwing exceptions so that the caller will know easily why the exception occurred. You should always avoid an empty “catch” block that just consumes the Exception and doesn’t offer meaningful details of the Exception for debugging.
f) Single catch block for multiple exceptions: You should use Java 7's feature to handle multiple exceptions in a single “catch” block. This approach reduces the code size and makes it look cleaner, too.
g) Using Custom Exceptions: It’s always better to define an exception handling strategy during design time. Rather than “throwing” and “catching” multiple exceptions, consider creating your custom exception with an error code, so that the caller program can handle these error codes. Making a utility method to process and use different error codes is also a good idea.
h) Naming Conventions and Packaging: When you create a custom exception, ensure that it ends with “Exception” so that it will be apparent from the name itself that it’s an exception class. Also, package them as you do in the Java Development Kit (JDK). For instance, “IOException” is the base exception for all IO operations.
Common Exceptions and Errors
Here are some common exceptions and errors that you might run into from time to time during Exception Handling in Java:
1) Checked Exceptions
a) IOException: This exception is a way to infer that something on the network, database or filesystem has failed.
2) RuntimeExceptions
a) ArrayIndexOutOfBoundsException: This exception implies that you tried to access a non-existent array index, for example, trying to get index 6 from an array of length 3.
b) ClassCastException: This exception means that you tried to perform an illegal cast, for example trying to convert a "String" into a "List". You can avoid it by performing defensive "instanceof" checks before casting.
c) IllegalArgumentException: This exception is a way for you to say that one of the provided constructor parameters is invalid.
d) IllegalStateException: This exception says that your internal state, uch as the state of our object, is invalid.
e) NullPointerException: This exception means that you tried to reference a "null" object which ypu can usually avoid by either performing defensive "null" checks or by using "Optional".
f) NumberFormatException: This exception reveals your attempt to convert a String into a number, while the string contains illegal characters. For example, trying to convert “6f4” into a number.
3) Errors
a) StackOverflowError: This exception implies that the stack trace is too big which can often happen in massive applications. However, it usually means that you have some infinite recursion happening in your code.
b) NoClassDefFoundError: This exception means that a class had failed to load for either of two reasons: Not being on the classpath or failure in static initialisation.
c) OutOfMemoryError: This exception informs that the JVM doesn’t have any memory left to allocate for more objects. Often times, this is due to a memory leak.
Conclusion
Exception handling in Java is an invaluable method for managing runtime errors effectively. Exceptions can arise for various reasons, potentially disrupting your program’s flow. In this blog, we dive deep into understanding how to handle these exceptions proficiently. By the end, you'll have a solid grasp of exception-handling techniques, enhancing your coding skills and ensuring your programs run smoothly. Let’s explore how you can master exception handling in Java!
Learn about the primary concepts of Advance Java by signing up for our Introduction to Java EE Training course now!
Frequently Asked Questions
In case an exception is not caught (with a "catch" block), the runtime system will abort the program (i.e., crash), and an exception message will print to the console. The message typically includes the name of the exception type.
You can rethrow an exception in Java by utilising the "throw" keyword. This should be immediately followed by a reference to the exception object that was "caught".
The Knowledge Academy’s Knowledge Pass, a prepaid voucher, adds another layer of flexibility, allowing course bookings over a 12-month period. Join us on a journey where education knows no bounds.
The Knowledge Academy offers various Java Courses, including Java Programming, JavaScript for Beginners and Java Swing Development Training. These courses cater to different skill levels, providing comprehensive insights into How to Become a Java Developer.
Our Programming & DevOps blogs cover a range of topics related to Java, offering valuable resources, best practices, and industry insights. Whether you are a beginner or looking to advance your Java Programming skills, The Knowledge Academy's diverse courses and informative blogs have you covered.
The Knowledge Academy takes global learning to new heights, offering over 30,000 online courses across 490+ locations in 220 countries. This expansive reach ensures accessibility and convenience for learners worldwide.
Alongside our diverse Online Course Catalogue, encompassing 17 major categories, we go the extra mile by providing a plethora of free educational Online Resources like News updates, Blogs, videos, webinars, and interview questions. Tailoring learning experiences further, professionals can maximise value with customisable Course Bundles of TKA.
Upcoming Programming & DevOps Resources Batches & Dates
Date
Mon 9th Dec 2024
Mon 6th Jan 2025
Mon 13th Jan 2025
Mon 20th Jan 2025
Mon 27th Jan 2025
Mon 3rd Feb 2025
Mon 10th Feb 2025
Mon 17th Feb 2025
Mon 24th Feb 2025
Mon 3rd Mar 2025
Mon 10th Mar 2025
Mon 17th Mar 2025
Mon 24th Mar 2025
Mon 7th Apr 2025
Mon 14th Apr 2025
Mon 21st Apr 2025
Mon 28th Apr 2025
Mon 5th May 2025
Mon 12th May 2025
Mon 19th May 2025
Mon 26th May 2025
Mon 2nd Jun 2025
Mon 9th Jun 2025
Mon 16th Jun 2025
Mon 23rd Jun 2025
Mon 7th Jul 2025
Mon 14th Jul 2025
Mon 21st Jul 2025
Mon 28th Jul 2025
Mon 4th Aug 2025
Mon 11th Aug 2025
Mon 18th Aug 2025
Mon 25th Aug 2025
Mon 8th Sep 2025
Mon 15th Sep 2025
Mon 22nd Sep 2025
Mon 29th Sep 2025
Mon 6th Oct 2025
Mon 13th Oct 2025
Mon 20th Oct 2025
Mon 27th Oct 2025
Mon 3rd Nov 2025
Mon 10th Nov 2025
Mon 17th Nov 2025
Mon 24th Nov 2025
Mon 1st Dec 2025
Mon 8th Dec 2025
Mon 15th Dec 2025
Mon 22nd Dec 2025