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:
| Class | Purpose |
|---|---|
Throwable | Base class for all errors and exceptions |
Error | JVM errors (do not need to be handled manually) – e.g., OutOfMemoryError, StackOverflowError |
Exception | Exceptions that can (and should) be handled |
RuntimeException | Runtime exceptions (unchecked) – NullPointerException, ArrayIndexOutOfBoundsException, IllegalArgumentException, etc. |
Checked vs Unchecked Exceptions
| Type | Example | When it occurs | Is it declared in throws? | Is it handled? |
|---|---|---|---|---|
| Checked | IOException, SQLException, FileNotFoundException | Errors that are predictable at compile time (e.g., when working with files, networks) | ✅ Yes | Mandatory (try-catch or throws) |
| Unchecked (Runtime) | NullPointerException, IndexOutOfBoundsException, ArithmeticException | Errors that occur during runtime (usually due to bugs) | ❌ No | Can 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 declarethrows. - Extend
RuntimeException→ you do not need to declarethrows.
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-resourcesfor any IO/JDBC operations. - ✅ Catch only those exceptions that you can handle meaningfully.
- ✅ Do not use
ExceptionorThrowableincatchwithout reason. - ✅ Create custom exceptions for business logic.
- ✅ Do not use exceptions for regular flow control.
- ✅ Always log errors (
Logger,SLF4J,Logback, etc.).