Exception Handling
Exception Handling
Introduction to Errors & Exceptions
An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions. It is a signal that indicates a condition that requires special attention.
When an exception occurs, the normal execution of the program is halted, and the system attempts to find an exception handler to deal with the situation.
An exception is an error event or exceptional condition during program execution that prevents normal continuation.
It's an object automatically created by Java when an error is detected, containing information about the error.
Exception handling is a mechanism that allows programs to manage exceptions gracefully, preventing abrupt crashes by providing ways to detect and resolve errors that occur during runtime. This involves the use of
try-catchblocks to handle exceptions and ensure that the program can recover or terminate safely.Exception handling allows programs to manage exceptions and recover, preventing crashes.
Java addresses errors by dealing with exceptions.
Exceptions arise from:
Numeric overflow errors: Occur when the result of an arithmetic operation exceeds the maximum value that can be stored in the variable.
Type conversion errors: Happen when there is an attempt to convert a value of one data type into another type that is not supported or compatible.
Dividing by zero errors: Occur when a number is divided by zero, which is mathematically undefined and results in an
ArithmeticException.Trying to open a non-existent file: Attempting to open a file that does not exist or cannot be found in the specified location results in a
FileNotFoundException.Running out of memory: Occurs when the program requires more memory than is available, leading to an
OutOfMemoryError.Database and SQL issues: Problems that arise during database interactions, such as incorrect SQL syntax, connection errors, or data integrity violations.
Array index out of bounds: Occurs when trying to access an array element with an index that is outside the valid range (i.e., less than 0 or greater than or equal to the array length), resulting in an
ArrayIndexOutOfBoundsException.Trying to use a null object or reference: Attempting to access the methods or properties of an object that has a null reference leads to a
NullPointerException.
Common Exception Scenarios
File handling or database interactions commonly lead to exceptions.
A needed file cannot be found. When a program attempts to open or access a file that does not exist in the specified location, a
FileNotFoundExceptionis thrown.Lack of permissions to write to a database or file. Attempting to write data to a file or database without the necessary permissions results in a security exception or an
IOException.File or data field with the wrong type. When the data in a file or database field does not match the expected data type, a
ClassCastExceptionorNumberFormatExceptionmay occur.
Exceptions can occur when using classes, potentially due to incorrect usage. This can include passing invalid arguments to methods, calling methods in an inappropriate sequence, or attempting to perform operations that are not supported by the class.
Incorrect usage should result in an exception. When developers misuse a class or its methods, exceptions are thrown to indicate that the class is being used in a way that it was not designed to handle.
Importance of Exception Handling
Run-time errors cause program crashes. When a program encounters an unhandled exception during runtime, it typically terminates abruptly, leading to a crash.
Software failure is unacceptable. In many applications, software failure can have severe consequences, ranging from data loss to system instability or even endangering human lives.
Software should handle all possible run-time situations. Robust software should anticipate and handle potential runtime errors gracefully, ensuring that the program can continue to operate correctly or terminate safely without causing harm.
Approaches to Error-Checking
Ignore all but the most important errors.
Cleaner code, but misbehavior upon encountering unusual errors. While ignoring less critical errors can lead to cleaner and more concise code, it may also result in unexpected behavior or incorrect results when the program encounters unusual or unforeseen error conditions.
Address every error appropriately.
Cluttered code, but improved program reliability. However, some error conditions might be missed. Addressing every possible error scenario can result in more verbose and complex code, but it also improves the program's reliability and robustness. However, developers may still overlook certain error conditions or fail to handle them correctly.
Separate normal processing from error handling.
Preferred approach. Designing software with clear separation between normal processing logic and error-handling code is generally the preferred approach. This makes the code easier to understand, maintain, and debug.
Reasonably uncluttered code. By separating error-handling code from normal processing, the codebase remains clean and organized, enhancing readability and maintainability.
Java ensures handling of every error.
The Exception Class
All exceptions inherit from
java.lang.Exception. In Java, all exception classes are subclasses of thejava.lang.Exceptionclass, which is the root of the exception hierarchy. This inheritance ensures that all exceptions have a common set of properties and methods.Important methods:
printStackTrace(): Prints the method call sequence leading to the exception. This method is useful for debugging as it provides a stack trace that shows the sequence of method calls that led to the exception, allowing developers to identify the source of the error.getMessage()andgetLocalizedMessage(): Returns a detailed error message. These methods return a string that provides additional information about the exception, such as a description of the error that occurred. ThegetLocalizedMessage()method returns a message that is localized for the user's locale, if available.toString(): Returns the Exception class name and a detailed message. This method returns a string representation of the exception object, which includes the name of the exception class and a detailed error message.
The
Exceptionclass is derived from theThrowableclass, inheritingprintStackTrace()andgetMessage(). Thejava.lang.Exceptionclass is a subclass of thejava.lang.Throwableclass, from which it inherits methods likeprintStackTrace()andgetMessage(). TheThrowableclass is the superclass of all errors and exceptions in Java.
Exception Class Hierarchy
Exception
RuntimeException
ArithmeticException
NumberFormatException
ArrayIndexOutOfBoundsException
… other RuntimeExceptions
IOException
NoSuchMethodException
ClassNotFoundException
ClassCastException
NullPointerException
IllegalArgumentException
IndexOutOfBoundsException
Exception Handling: Mandatory in Java
Other languages might allow ignoring exceptions, leading to sloppy programs. In some programming languages, it is possible to ignore exceptions or errors, which can lead to poorly written programs that are difficult to debug and maintain.
Java forces exception handling for better program quality. Java requires developers to either handle exceptions using
try-catchblocks or declare that the method throws the exception using thethrowsclause. This forces developers to consider potential error conditions and handle them appropriately, leading to more robust and reliable code.
Dealing with Exceptions
Throwing an exception: Creating an object that represents an error. When an error condition is detected, an exception object is created to encapsulate information about the error, such as the type of error, a descriptive message, and the state of the program at the time the error occurred.
Handling an exception: Detecting and addressing the exception. Handling an exception involves detecting the error and taking appropriate action to resolve it or mitigate its impact on the program's execution.
Java throws an exception when an error occurs, creating an exception object. When an error occurs during program execution, Java automatically creates an exception object and throws it, signaling that an exceptional condition has arisen.
The program can catch the object and attempt recovery, or ignore it, leading to a crash. When an exception is thrown, the program can either catch the exception and attempt to recover from the error, or ignore it, which will typically result in the program terminating with an error message.
Common Exception Types
NullPointerException: Attempting to use a null object. This exception occurs when the program tries to access the methods or properties of an object that has a null reference, meaning that it does not point to any actual object in memory.ClassCastException: Incorrect type casting. This exception is thrown when the program attempts to cast an object to a class of which it is not an instance or a subclass.ArithmeticException: Arithmetic error (e.g., division by zero). This exception occurs when an arithmetic operation, such as division, results in an error condition, such as dividing a number by zero.NumberFormatException: Incorrect number format. This exception is thrown when the program tries to convert a string to a numeric type, but the string does not have the appropriate format (e.g., attempting to convert "abc" to an integer).IOException: Input/output problem. This exception is a general exception that occurs when there is a problem with input or output operations, such as reading from or writing to a file.FileNotFoundException: File not found. This exception is thrown when the program attempts to open or access a file that does not exist in the specified location.EOFException: Attempt to read past the end of a file. This exception occurs when the program tries to read data from a file, but the end of the file has been reached.There exist over 200 pre-defined exceptions. In Java, there are more than 200 predefined exception classes that cover a wide range of error conditions that may occur during program execution. These exceptions are organized into a hierarchy, with the
java.lang.Exceptionclass as the root.
Try-Catch Control Structure
Java's control structure for exception handling:
Try-Catch. Thetry-catchblock is a fundamental control structure in Java for handling exceptions. It allows developers to enclose a block of code that may potentially throw an exception within atryblock and provide one or morecatchblocks to handle specific types of exceptions that may occur.Separates normal code from error-handling code. The
try-catchblock separates the normal flow of execution from the error-handling logic, making the code more organized and easier to understand. Thetryblock contains the code that is likely to throw an exception, while thecatchblocks contain the code that handles the exception if it occurs.Syntax:
try { // statements to try that may cause an exception } catch (Exception ex) { // statements to execute when an exception occurs }
Complete Try-Catch Syntax
String[] students = {"Bob", "Steve", "Larry"};
try {
// statements to try that may cause an exception
} [
catch (MostSpecificExceptionType exceptionName) {
// statements to execute when an exception occurs
}
] [
catch (NextSpecificExceptionType exceptionName) {
// statements to execute when an exception occurs
}
] [
catch (LeastSpecificExceptionType exceptionName) {
// statements to execute when an exception occurs
}
] [
finally {
// statements that always execute after the try-catch,
// regardless of whether or not an exception occurred.
}
]
How Try-Catch Works
Code in the
Tryblock executes. The code inside thetryblock is executed in a protected region. If an exception occurs during the execution of this code, the control is transferred to the appropriatecatchblock.Catchphrases are skipped if no exceptions occur. If the code inside thetryblock executes without throwing any exceptions, thecatchblocks are skipped, and the program continues with the code after thetry-catchblock.If an exception arises, the program jumps to the first applicable
Catchclause. When an exception is thrown within thetryblock, the program searches for the firstcatchblock that can handle the exception. Thecatchblock must specify an exception type that is the same as or a superclass of the exception type thrown.Finallycode executes regardless of exceptions. Thefinallyblock is an optional block that contains code that is always executed, regardless of whether an exception was thrown or caught. This is often used to release resources or perform cleanup operations.
The Finally Block
The
Finallyblock always executes in theTry-Catch-Finallystructure. Thefinallyblock is guaranteed to be executed regardless of whether an exception is thrown or caught. It is typically used to release resources, such as closing files or releasing database connections, to prevent resource leaks.If no exception occurs, it executes after the
trycode. If the code in thetryblock executes without throwing any exceptions, thefinallyblock is executed after thetryblock.If an exception occurs, it executes after the appropriate
catchcode. If an exception is thrown and caught by acatchblock, thefinallyblock is executed after thecatchblock.It executes even with a
returnstatement intryorcatchblocks, but before thereturnis executed. Even if thetryorcatchblocks contain areturnstatement, thefinallyblock is executed before the method returns. This ensures that resources are released or cleanup operations are performed before the method exits.A
returnstatement cannot be included in afinallyblock. It is generally not recommended to include areturnstatement in afinallyblock because it can override the return value of thetryorcatchblocks, leading to unexpected behavior.
Try-Catch Example
String input;
double rate;
double amount;
try {
input = JOptionPane.showInputDialog("Enter the rate");
rate = Double.parseDouble(input);
input = JOptionPane.showInputDialog("Enter the amount");
amount = Double.parseDouble(input);
amount = amount * (1 + rate);
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "An error occurred: " + ex.getMessage());
rate = 0;
amount = 0;
}
JOptionPane.showMessageDialog(null, "The total is $" + amount);
Issue: The
finallyblock execution means that rate and amount are reset to zero even when no problems are encountered, so the output will display $0.00.
Ordering Catch Statements
Multiple
Catchstatements can follow aTry. Atryblock can be followed by multiplecatchblocks, each of which handles a different type of exception. This allows the program to handle different error conditions separately and take appropriate action for each.The first
Catchthat can handle the exception catches it. When an exception is thrown, the program searches for the firstcatchblock that can handle the exception. Thecatchblock must specify an exception type that is the same as or a superclass of the exception type thrown.Order
catchstatements from most specific to most general. When multiplecatchblocks are present, they should be ordered from most specific to most general. This ensures that the most specific exception is caught by the appropriatecatchblock, rather than being caught by a more generalcatchblock.Example:
try { // try statement block } catch (EOFException ex) { // catch statement block } catch (FileNotFoundException ex) { // catch statement block } catch (IOException ex) { // catch statement block } catch (Exception ex) { // catch statement block }
Checked vs. Unchecked Exceptions
Checked exceptions: Compiler-recognized exceptions (e.g.,
FileNotFoundException,EndOfFileException,Exception, excludingRuntimeException). Checked exceptions are exceptions that the compiler requires to be either caught or declared as thrown by the method. If a method throws a checked exception, it must be declared in the method'sthrowsclause.Methods throwing checked exceptions must declare it using the
throwsstatement. When a method throws a checked exception, it must declare the exception in itsthrowsclause. This informs the caller of the method that the method may throw the exception, and the caller must either catch the exception or declare that it throws the exception as well.
Unchecked exceptions: Compiler cannot determine at compile time (e.g.,
RuntimeException, potential divide-by-zero). Unchecked exceptions are exceptions that the compiler does not require to be caught or declared as thrown by the method. These exceptions typically indicate programming errors, such as null pointer exceptions or array index out of bounds exceptions.The compiler doesnt check unchecked exceptions, so the throws statement isnt required. Because the compiler does not check unchecked exceptions, methods are not required to declare that they throw these exceptions in their
throwsclauses.
Throwing Exceptions
The
throwstatement is used to create exceptions and mark methods that may throw checked exceptions. Thethrowstatement is used to explicitly throw an exception in Java. This allows developers to signal that an error condition has occurred and transfer control to the appropriate exception handler.When to throw:
Improper use of a class or its methods. If a class or its methods are used in an incorrect or inappropriate way, an exception may be thrown to indicate that the class is being misused.
Method unable to complete its task. If a method is unable to complete its task due to an error