Sobes.tech
Junior

How are errors handled in Java and how to work with them?

sobes.tech AI

Answer from AI

In Java, errors are handled using the exception mechanism. Exceptions represent events that disrupt the normal flow of program execution. There are two types of exceptions: Checked Exceptions and Unchecked Exceptions.

Checked Exceptions:

  • Inherit from java.lang.Exception (except RuntimeException).
  • Must be handled (using try-catch) or declared in the method signature (using throws).
  • Represent errors that can occur under normal conditions (e.g., IOException, FileNotFoundException).

Unchecked Exceptions:

  • Inherit from java.lang.RuntimeException or java.lang.Error.
  • Do not require mandatory handling or declaration.
  • Represent errors that often indicate logical errors in code or abnormal runtime states (e.g., NullPointerException, ArrayIndexOutOfBoundsException).

Exception Handling:

For handling exceptions, try-catch-finally blocks are used:

  • try: Block of code that may generate an exception.
  • catch: Block of code that executes if an exception of the specified type occurs in the try block. Multiple catch blocks can be used for different exception types.
  • finally: Block of code that executes regardless of whether an exception occurred or not. Often used for resource cleanup (e.g., closing files, connections).
try {
    // Code that may throw an exception
    int result = 10 / 0; // Example: ArithmeticException
} catch (ArithmeticException e) {
    // Handling ArithmeticException
    System.err.println("Division by zero error: " + e.getMessage());
    // Logging the error, showing message to user, etc.
} catch (Exception e) {
    // Handling any other exception not previously handled
    System.err.println("A general error occurred: " + e.getMessage());
} finally {
    // Code that always executes
    System.out.println("Finally block executed.");
}

Exception Propagation:

A method can declare that it may throw a specific exception using the throws keyword:

public void readFile(String filePath) throws FileNotFoundException, IOException {
    // Code to read a file
    // If the file is not found, FileNotFoundException may be thrown (a subclass of IOException)
    FileReader fr = new FileReader(filePath);
    // If an I/O error occurs, IOException may be thrown
    // ...
}

The calling method must either handle this exception (try-catch) or also declare that it throws it.

Creating Custom Exceptions:

Custom exception classes can be created by inheriting from Exception (for Checked Exceptions) or RuntimeException (for Unchecked Exceptions).

public class MyCustomException extends Exception {
    public MyCustomException(String message) {
        super(message);
    }
}

Usage:

public void processData(int value) throws MyCustomException {
    if (value < 0) {
        throw new MyCustomException("Value cannot be negative");
    }
    // Process data
}

Main exception classes hierarchy:

  • java.lang.Throwable (base class for all errors and exceptions)
    • java.lang.Error (for serious problems usually not handled by the program, e.g., OutOfMemoryError)
    • java.lang.Exception (for exceptions the program can handle)
      • java.lang.RuntimeException (Unchecked Exceptions)
        • NullPointerException
        • ArrayIndexOutOfBoundsException
        • ArithmeticException
        • etc.
      • Other subclasses of Exception (Checked Exceptions)
        • IOException
        • FileNotFoundException
        • SQLException
        • etc.

Working with errors involves understanding this hierarchy, choosing the appropriate exception type (when creating custom ones), effectively using try-catch-finally for handling and propagating exceptions, and logging errors for debugging.