Exception Handling - Notes By ShariqSP
Exception Handling in Java
Exception handling in Java is a mechanism to handle runtime errors such as exceptions and errors. Exceptions are unexpected events that occur during the execution of a program and disrupt its normal flow. By using exception handling, you can gracefully manage these unexpected situations and ensure that your program does not terminate abruptly.
Types of Exceptions:
Java exceptions are divided into two categories: checked exceptions and unchecked exceptions.
- Checked Exceptions: These are exceptions that are checked at compile time. This means that the compiler checks whether the code that may throw a checked exception is surrounded by a try-catch block or if the method declares that it throws the exception using the
throws
keyword. - Unchecked Exceptions: Also known as runtime exceptions, these exceptions are not checked at compile time. They occur during the execution of the program and can be handled using try-catch blocks, but it is not mandatory to do so.
Exception Handling Keywords:
Java provides several keywords for exception handling:
- try: This keyword defines a block of code that may throw an exception. It is followed by one or more catch blocks or a finally block.
- catch: This keyword is used to catch and handle exceptions. It is preceded by a try block and followed by a block of code that handles the exception.
- finally: This keyword defines a block of code that is always executed, regardless of whether an exception occurs or not. It is typically used to release resources.
- throw: This keyword is used to manually throw an exception. It is followed by an instance of the exception class that you want to throw.
- throws: This keyword is used in method signatures to declare that the method may throw certain exceptions. It specifies the exceptions that can be thrown by the method but does not handle them.
Example:
try {
// Code that may throw an exception
int result = 10 / 0; // This will throw an ArithmeticException
} catch (ArithmeticException e) {
// Handling the exception
System.out.println("An arithmetic exception occurred: " + e.getMessage());
} finally {
// Code that will always be executed
System.out.println("Finally block executed.");
}
In this example, the try
block contains code that may throw an ArithmeticException
(division by zero). If the exception occurs, it is caught by the catch
block, which handles it by printing a message. The finally
block is always executed, regardless of whether an exception occurs or not.
Checked Exceptions in Java
Checked exceptions are exceptions that are checked at compile time. This means that the compiler checks whether the code that may throw a checked exception is surrounded by a try-catch block or if the method declares that it throws the exception using the throws
keyword. If the code does not handle the checked exception, the compiler will generate a compilation error.
When Checked Exceptions Occur:
Checked exceptions occur in situations where external factors, such as user input, file I/O operations, or network communication, may fail or cause an error condition.
How to Handle Checked Exceptions:
Checked exceptions can be handled using try-catch blocks or by declaring the exception in the method signature using the throws
keyword. By handling checked exceptions, you can ensure that your program gracefully handles potential errors and continues to execute without terminating abruptly.
List of Checked Exceptions in Java:
- IOException: This exception is thrown when an I/O operation fails or is interrupted.
- FileNotFoundException: This exception is thrown when a file specified by a program cannot be found.
- ParseException: This exception is thrown when a parse operation fails, such as parsing a string to a date.
- SQLException: This exception is thrown when an error occurs while accessing a database.
- ClassNotFoundException: This exception is thrown when a class specified in code is not found at runtime.
- InterruptedException: This exception is thrown when a thread is interrupted while it is waiting, sleeping, or performing a blocking I/O operation.
Example:
import java.io.*;
public class Main {
public static void main(String[] args) {
try {
FileReader file = new FileReader("file.txt");
BufferedReader br = new BufferedReader(file);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
} catch (IOException e) {
System.out.println("Error reading file: " + e.getMessage());
}
}
}
In this example, the program attempts to read from a file named "file.txt". If the file is not found (FileNotFoundException
) or an error occurs while reading the file (IOException
), the program handles the exception by printing an appropriate error message.
Unchecked Exceptions in Java
Unchecked exceptions, also known as runtime exceptions, are exceptions that are not checked at compile time. Unlike checked exceptions, the compiler does not enforce handling of unchecked exceptions. Unchecked exceptions occur during the execution of the program and can be caused by various factors such as programming errors, invalid input, or unexpected conditions.
When Unchecked Exceptions Occur:
Unchecked exceptions occur at runtime when the JVM encounters an error condition that it cannot recover from. These exceptions are typically caused by programming errors such as null pointer dereference, array index out of bounds, or arithmetic overflow.
How to Handle Unchecked Exceptions:
While it is not mandatory to handle unchecked exceptions, it is good practice to handle them when possible to prevent unexpected termination of the program. Unchecked exceptions can be handled using try-catch blocks, but it is also important to identify and fix the root cause of the exception to prevent it from occurring again.
List of Unchecked Exceptions in Java:
- NullPointerException: This exception is thrown when an application attempts to access or modify a null object reference.
- ArrayIndexOutOfBoundsException: This exception is thrown when an attempt is made to access an array element at an index that is outside the bounds of the array.
- ArithmeticException: This exception is thrown when an arithmetic operation results in an overflow, underflow, or division by zero.
- NumberFormatException: This exception is thrown when an attempt is made to convert a string to a numeric type, but the string does not contain a valid numeric value.
- ClassCastException: This exception is thrown when an attempt is made to cast an object to a subclass type that is not compatible with the object's actual type.
- IllegalArgumentException: This exception is thrown when a method receives an illegal or inappropriate argument.
Example:
public class Main {
public static void main(String[] args) {
try {
int[] numbers = {1, 2, 3};
System.out.println(numbers[4]); // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out of bounds: " + e.getMessage());
}
}
}
In this example, the program attempts to access an element at index 4 in an array with only 3 elements. This results in an ArrayIndexOutOfBoundsException
, which is caught and handled by the catch block.
Throwable in Java
In Java, Throwable
is the superclass of all classes that represent errors or exceptions that can be thrown during the execution of a program. It serves as the base class for both checked and unchecked exceptions, as well as for errors.
Hierarchy of Throwable:
The Throwable
class is at the top of the exception hierarchy in Java. It has two direct subclasses:
- Error: Represents serious errors that are beyond the control of the application and typically cannot be recovered from. Examples include
OutOfMemoryError
andStackOverflowError
. - Exception: Represents exceptional conditions that can be caught and handled by the application. Exceptions are further divided into checked exceptions and unchecked exceptions.
Throwable Methods:
The Throwable
class provides several methods for working with exceptions:
- getMessage(): Returns a detailed message describing the cause of the exception.
- getCause(): Returns the cause of the exception, or
null
if the cause is unknown. - printStackTrace(): Prints the stack trace of the exception to the standard error stream. This method is useful for debugging.
- toString(): Returns a string representation of the exception, including its class name and message.
- getStackTrace(): Returns an array of
StackTraceElement
objects representing the stack trace of the exception. - fillInStackTrace(): Fills in the execution stack trace of the exception. This method is typically called from within a constructor to capture the current stack trace at the point where the exception was created.
- initCause(Throwable cause): Initializes the cause of the exception. This method is useful for chaining exceptions.
Example:
public class Main {
public static void main(String[] args) {
try {
throw new NullPointerException("Custom exception message");
} catch (NullPointerException e) {
System.out.println("Caught exception: " + e.getMessage());
e.printStackTrace();
}
}
}
In this example, a NullPointerException
is explicitly thrown using the throw
keyword. The exception is caught and its message is printed, along with the stack trace.
The finally Block in Java
In Java, the finally
block is used to define a block of code that will be executed regardless of whether an exception occurs or not. It provides a way to ensure that certain cleanup or resource release tasks are performed, even if an exception is thrown and caught elsewhere in the code.
Usage of the finally Block:
The finally
block is typically used in conjunction with a try-catch
block. It follows the try
block and is executed after the try
block completes, regardless of whether an exception occurs or not. The finally
block is useful for releasing resources, closing connections, or performing other cleanup tasks.
Key Points about the finally Block:
- The
finally
block is optional, but if present, it must follow either atry
block or atry-catch
block. - The
finally
block will be executed even if an exception is thrown and caught within thetry
block. - The
finally
block will be executed even if an exception is thrown but not caught within thetry
block. - The
finally
block will be executed even if areturn
statement is encountered within thetry
block. - If a
finally
block is present, it will be executed before the method returns, even if areturn
statement is encountered within thefinally
block itself.
Example:
public class Main {
public static void main(String[] args) {
try {
// Code that may throw an exception
System.out.println("Try block executed");
throw new RuntimeException("Custom exception message");
} catch (RuntimeException e) {
// Catching the exception
System.out.println("Exception caught: " + e.getMessage());
} finally {
// Finally block for cleanup tasks
System.out.println("Finally block executed");
}
}
}
In this example, even though an exception is thrown and caught within the try
block, the finally
block is still executed before the program terminates. This ensures that any cleanup tasks defined in the finally
block are performed, regardless of whether an exception occurs or not.
The throw Keyword in Java
In Java, the throw
keyword is used to explicitly throw an exception within a program. It allows you to create and throw custom exceptions or to rethrow exceptions that are caught but cannot be handled locally.
Usage of the throw Keyword:
The throw
keyword is followed by an instance of a subclass of Throwable
(usually an exception object). When the throw
statement is encountered, the specified exception is thrown and the normal flow of the program is interrupted. The exception is then propagated up the call stack until it is caught by an appropriate try-catch
block or handled by the default exception handler.
Key Points about the throw Keyword:
- The
throw
keyword is used to throw an exception explicitly within the code. - It is typically used to raise exceptions for exceptional conditions that are not handled by the normal flow of the program.
- The exception thrown using the
throw
keyword must be an object of a class that is a subclass ofThrowable
. - The
throw
statement must be enclosed within a method or constructor. - Once an exception is thrown using the
throw
keyword, the program flow is immediately transferred to the nearest enclosingtry-catch
block or the default exception handler.
Examples:
Example with Array:
public class Main {
public static void main(String[] args) {
int[] numbers = {1, 2, 3};
int index = 4;
if (index >= numbers.length) {
throw new ArrayIndexOutOfBoundsException("Index out of bounds");
}
System.out.println("Value at index " + index + ": " + numbers[index]);
}
}
In this example, the throw
keyword is used to explicitly throw an ArrayIndexOutOfBoundsException
if the specified index is out of bounds for the array. This prevents the program from accessing an invalid index and potentially causing a runtime error.
Example with String:
public class Main {
public static void main(String[] args) {
String str = null;
if (str == null) {
throw new NullPointerException("String is null");
}
System.out.println("Length of string: " + str.length());
}
}
In this example, the throw
keyword is used to explicitly throw a NullPointerException
if the string is null
. This prevents the program from attempting to access the length of a null
string, which would result in a runtime error.
The throws Keyword in Java
In Java, the throws
keyword is used in method declarations to indicate that the method may throw certain exceptions. It specifies the exceptions that can be thrown by the method but does not handle them. Instead, it delegates the responsibility of handling the exceptions to the caller of the method.
Usage of the throws Keyword:
The throws
keyword is followed by a comma-separated list of exception classes. These classes represent the exceptions that the method may throw during its execution. When a method is declared with the throws
keyword, the caller of the method is responsible for handling the specified exceptions using a try-catch
block or by declaring them in its own throws
clause.
Key Points about the throws Keyword:
- The
throws
keyword is used in method declarations to indicate that the method may throw certain exceptions. - It is followed by a comma-separated list of exception classes.
- It specifies the exceptions that can be thrown by the method but does not handle them.
- When a method is declared with the
throws
keyword, the caller of the method is responsible for handling the specified exceptions. - The caller can handle the exceptions using a
try-catch
block or by declaring them in its ownthrows
clause.
Example:
public class Main {
public static void main(String[] args) {
try {
// Calling a method that throws an exception
methodWithException();
} catch (Exception e) {
System.out.println("Exception caught: " + e.getMessage());
}
}
public static void methodWithException() throws Exception {
// Method declaration with throws keyword
throw new Exception("Custom exception message");
}
}
In this example, the methodWithException
method is declared with the throws
keyword to indicate that it may throw an exception of type Exception
. When calling this method, the caller must handle the potential exception using a try-catch
block or by declaring it in its own throws
clause.
Difference between throw and throws
Keyword | Usage | Responsibility | Handling |
---|---|---|---|
throw |
Used to explicitly throw an exception within the code. | The responsibility of throwing the exception lies with the programmer. | Exceptions thrown using throw must be caught and handled using a try-catch block. |
throws |
Used in method declarations to indicate that the method may throw certain exceptions. | The responsibility of handling the specified exceptions lies with the caller of the method. | Exceptions specified in the throws clause must be caught and handled by the caller using a try-catch block or by declaring them in its own throws clause. |
Difference between final, finally, and finalize
Keyword | Usage | Responsibility | Scope |
---|---|---|---|
final |
Used to declare constants, make variables immutable, and prevent method overriding or class inheritance. | The responsibility of marking a variable, method, or class as immutable or final lies with the programmer. | Can be applied to variables, methods, and classes. |
finally |
Used in try-catch blocks to define a block of code that will be executed regardless of whether an exception occurs or not. |
The responsibility of defining cleanup tasks or resource release operations lies with the programmer. | Can only be used within try-catch blocks. |
finalize |
Used in Java to perform cleanup operations on objects before they are garbage collected. | The responsibility of defining cleanup tasks for objects lies with the programmer. | Only applies to object-oriented programming and can be overridden by subclasses. |
Interview Questions on Exception Handling in Java
Interview Questions:
- What is exception handling in Java?
- Explain the purpose of try-catch blocks in exception handling.
- What are the advantages of using exception handling?
- What is the difference between checked exceptions and unchecked exceptions?
- When do checked exceptions occur?
- What are some common checked exceptions in Java?
- What is the significance of the throws keyword in exception handling?
- Explain the role of the finally block in exception handling.
- How do you create custom exceptions in Java?
- What is the purpose of the throw keyword in exception handling?
- What is the difference between throw and throws in exception handling?
- Explain the concept of exception propagation.
- What is the use of the try-with-resources statement?
- What is the role of the catch block in exception handling?
- How do you handle multiple exceptions in a single catch block?
- What is the difference between Error and Exception in Java?
- What is the purpose of the getMessage() method in the Throwable class?
- How do you handle exceptions in multithreaded programs?
- Explain the concept of exception chaining in Java.
- What are the best practices for exception handling in Java?
Multiple Choice Questions (MCQs):
- Which keyword is used to handle exceptions in Java?
a) catch
b) try
c) throw
d) All of the above
Answer: d) All of the above - Which keyword is used to specify that a method may throw an exception?
a) catch
b) try
c) throws
d) throw
Answer: c) throws - Which block is used to write the code that may throw an exception?
a) try
b) catch
c) finally
d) throw
Answer: a) try - Which block is used to handle the exceptions in Java?
a) try
b) catch
c) finally
d) All of the above
Answer: b) catch - Which block is used to write the cleanup code in exception handling?
a) try
b) catch
c) finally
d) All of the above
Answer: c) finally