RU | EN | DE

What is an Exception

Exception is an event that interrupts the normal execution flow of a program. When an error occurs, Java creates a Throwable class object and passes it to the runtime environment (JVM). If an exception is not caught (try-catch), the program terminates with an error.

The Throwable Hierarchy

java.lang.Object
  └── java.lang.Throwable
    ├── Exception
  │   └── RuntimeException
  │   └── ... (other checked exceptions)
  └── Error

📗 Explanation of Branches:

ClassPurpose
ThrowableBase class for all errors and exceptions
ErrorJVM errors (do not need to be handled manually) – e.g., OutOfMemoryError, StackOverflowError
ExceptionExceptions that can (and should) be handled
RuntimeExceptionRuntime exceptions (unchecked) – NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException, etc.

Checked vs Unchecked Exceptions

TypeExampleWhen it occursIs it declared in throws?Is it handled?
CheckedIOException, SQLException, FileNotFoundExceptionErrors that are predictable at compile time (e.g., when working with files, networks)✅ YesMandatory (try-catch or throws)
Unchecked (Runtime)NullPointerException, IndexOutOfBoundsException, ArithmeticExceptionErrors that occur during runtime (usually due to bugs)❌ NoCan be handled, but not required

📙 Example: Checked Exception

import java.io.FileReader;
import java.io.IOException;
public class CheckedExample {
  public static void main(String[] args) {
  try {
  FileReader reader = new FileReader("data.txt");
  reader.read();
  reader.close();
  } catch (IOException e) {
  System.out.println("Error reading file: " + e.getMessage());
  }
  }
}

💡 Without a try-catch block, the compiler will not allow the code to run because FileReader throws IOException.

📙 Example: Unchecked Exception

public class UncheckedExample {
  public static void main(String[] args) {
  int[] nums = {1, 2, 3};
  System.out.println(nums[5]); // ArrayIndexOutOfBoundsException
  }
}

💡 Can be compiled, but will result in an error during runtime.

try, catch, finally Blocks

✅ Basic Syntax

try {
  // code that may throw an exception
} catch (ExceptionType e) {
  // exception handling
} finally {
  // executes always, regardless of whether an exception occurred
}

📙 Example:

try {
  int result = 10 / 0;
} catch (ArithmeticException e) {
  System.out.println("Division by zero!");
} finally {
  System.out.println("Operation completed");
}
Output:
Division by zero!
Operation completed

💡 finally is executed always, even if there is a return in the catch block.

try-with-resources (Java 7+)

Purpose: Automatically closes resources (e.g., files, streams, connections) that implement the AutoCloseable interface.

Syntax:

try (FileReader reader = new FileReader("data.txt")) {
  int c = reader.read();
} catch (IOException e) {
  e.printStackTrace();
}

💡 After exiting the try block, the reader.close() method is called automatically, even if an exception occurs. 📍 Works with any object implementing AutoCloseable or Closeable.

Example with JDBC:

try (Connection conn = DriverManager.getConnection(url);
  PreparedStatement stmt = conn.prepareStatement(sql)) {
  stmt.executeUpdate();
} catch (SQLException e) {
  e.printStackTrace();
}

throw and throws Keywords

throw – throws an exception manually

if (age < 0) {
  throw new IllegalArgumentException("Age cannot be negative!");
}

💡 Used to generate errors in code or validate data.

throws – declares that a method can throw an exception

void readFile(String path) throws IOException {
  FileReader reader = new FileReader(path);
}

💡 Declaring throws is required for checked exceptions if they are not caught within the method.

Multiple catch Blocks

try {
  FileReader reader = new FileReader("file.txt");
  int x = 10 / 0;
} catch (FileNotFoundException e) {
  System.out.println("File not found");
} catch (ArithmeticException e) {
  System.out.println("Division error");
} catch (Exception e) {
  System.out.println("General error");
}

📍 catch blocks are checked from top to bottom, from more specific to more general.

Multiple catch (Java 7+)

If you need to handle multiple exceptions in the same way, you can combine them:

try {
  // ...
} catch (IOException | SQLException e) {
  e.printStackTrace();
}

Creating Custom Exceptions

You can create your own exception by extending Exception or RuntimeException.

Checked custom exception:

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

Unchecked custom exception:

class MyRuntimeException extends RuntimeException {
  public MyRuntimeException(String message) {
    super(message);
  }
}

📍 Difference:

  • Extend Exception → you need to declare throws.
  • Extend RuntimeException → you do not need to declare throws.

Typical Errors

❌ Exception swallowing:

try {
  doSomething();
} catch (Exception e) {
  // empty – bad!
}

✅ Better:

try {
  doSomething();
} catch (Exception e) {
  log.error("Error performing operation", e);
  throw e; // or wrap in a custom exception
}

❌ Incorrect catch order:

try { ... }
catch (Exception e) { ... }
catch (IOException e) { ... } // unreachable code

✅ Correct – from specific to general.

⚙️Best Practices

  • ✅ Use try-with-resources for any IO/JDBC operations.
  • ✅ Catch only those exceptions that you can handle meaningfully.
  • ✅ Do not use Exception or Throwable in catch without reason.
  • ✅ Create custom exceptions for business logic.
  • ✅ Do not use exceptions for regular flow control.
  • ✅ Always log errors (Logger, SLF4J, Logback, etc.).