Java Notes
Complete guide to Exception Handling in Java covering what exceptions are, why they occur, the exception handling mechanism, types of errors, and how Java
What is an Exception?
An exception is an unwanted or unexpected event that disrupts the normal flow of a program's execution at runtime. When an exceptional condition arises, an object representing that error is created and "thrown" in the method that caused it.
Think of it this way: You're driving on a highway (your program is executing). Suddenly, there's a roadblock (an exception occurs). You have two choices:
- Crash into it (program terminates abnormally)
- Take a detour and continue your journey (handle the exception gracefully)
Exception handling gives you the power to take that detour.
Why Do Exceptions Occur?
Exceptions can occur due to many reasons:
| Cause | Example |
|---|---|
| Invalid user input | Entering "abc" when a number is expected |
| File not found | Trying to read a file that doesn't exist |
| Network failure | Server is down during API call |
| Null reference | Calling a method on a null object |
| Array out of bounds | Accessing index 10 in a 5-element array |
| Arithmetic error | Dividing a number by zero |
| Class not found | Required JAR file is missing |
| Out of memory | JVM runs out of heap space |
Error vs Exception
Understanding the difference between errors and exceptions is crucial:
Errors (Unrecoverable)
- Represent serious problems that a reasonable application should not try to catch
- Usually caused by the environment (JVM, hardware)
- Examples:
OutOfMemoryError,StackOverflowError,VirtualMachineError - You typically cannot recover from these
Exceptions (Recoverable)
- Represent conditions that a reasonable application might want to catch
- Caused by the application code or external resources
- Examples:
IOException,NullPointerException,SQLException - You CAN and SHOULD handle these
What Happens Without Exception Handling?
public class WithoutHandling {
public static void main(String[] args) {
System.out.println("Program started");
int result = 10 / 0; // ArithmeticException occurs here
// These lines will NEVER execute
System.out.println("Result: " + result);
System.out.println("Program ended normally");
}
}Output:
Notice how the program abruptly terminated — the remaining statements never executed. In a real application (like a banking system), this could mean a half-completed transaction, corrupted data, or a terrible user experience.
What Happens With Exception Handling?
public class WithHandling {
public static void main(String[] args) {
System.out.println("Program started");
try {
int result = 10 / 0; // ArithmeticException occurs here
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Error: Cannot divide by zero!");
System.out.println("Message: " + e.getMessage());
}
// This line WILL execute
System.out.println("Program ended normally");
}
}Output:
The program continued executing after handling the exception. This is the power of exception handling.
The Exception Handling Mechanism in Java
Java uses five keywords for exception handling:
| Keyword | Purpose |
|---|---|
try | Encloses code that might throw an exception |
catch | Handles the exception thrown by the try block |
finally | Executes code regardless of exception occurrence |
throw | Manually throws an exception |
throws | Declares that a method might throw an exception |
Basic Syntax Structure
try {
// Risky code that might throw exception
} catch (ExceptionType1 e1) {
// Handle ExceptionType1
} catch (ExceptionType2 e2) {
// Handle ExceptionType2
} finally {
// Always executes (cleanup code)
}Types of Exceptions
1. Checked Exceptions (Compile-time Exceptions)
- Checked by the compiler at compile time
- You MUST either handle them (try-catch) or declare them (throws)
- Examples:
IOException,SQLException,FileNotFoundException,ClassNotFoundException
import java.io.FileReader;
import java.io.IOException;
public class CheckedExample {
public static void main(String[] args) {
// This won't compile without try-catch or throws declaration
try {
FileReader reader = new FileReader("nonexistent.txt");
int data = reader.read();
reader.close();
} catch (IOException e) {
System.out.println("File error: " + e.getMessage());
}
}
}Output:
2. Unchecked Exceptions (Runtime Exceptions)
- NOT checked at compile time
- Subclasses of
RuntimeException - Usually caused by programming bugs
- Examples:
NullPointerException,ArrayIndexOutOfBoundsException,ArithmeticException
Output:
Real-World Analogy
Think of exception handling like a safety net for trapeze artists:
| falls | |
|---|---|
| falls |
A Complete Real-World Example
=== Welcome to Java Bank ATM === 1. Check Balance 2. Deposit 3. Withdraw 4. Exit Enter choice: 2 Enter amount: 500 Deposited: 500.0 New Balance: 1500.0 Enter choice: 3 Enter amount: 2000 Error: Insufficient balance! Your balance: 1500.0
How the JVM Handles Exceptions Internally
When an exception occurs, the JVM follows these steps:
- Exception Object Creation: JVM creates an exception object containing:
- Name of the exception
- Description/message
- Stack trace (method call history)
- Stack Unwinding: JVM searches the call stack from top to bottom for an appropriate exception handler
- Handler Search:
- If a matching
catchblock is found → control transfers there - If no handler is found → the default exception handler takes over
- Default Handler Behavior: Prints the exception info and terminates the program
public class StackUnwinding {
public static void main(String[] args) {
try {
method1();
} catch (ArithmeticException e) {
System.out.println("Exception caught in main!");
System.out.println("Stack trace:");
e.printStackTrace();
}
}
static void method1() {
method2();
}
static void method2() {
method3();
}
static void method3() {
int result = 10 / 0; // Exception thrown here
}
}Output:
| java.lang.ArithmeticException | / by zero |
| at StackUnwinding.method3(StackUnwinding.java | 22) |
| at StackUnwinding.method2(StackUnwinding.java | 18) |
| at StackUnwinding.method1(StackUnwinding.java | 14) |
| at StackUnwinding.main(StackUnwinding.java | 5) |
Notice how the exception "bubbled up" from method3 → method2 → method1 → main, where it was finally caught.
Common Mistakes Beginners Make
1. Ignoring Exceptions (Empty Catch Block)
// ❌ WRONG - Never do this!
try {
riskyOperation();
} catch (Exception e) {
// Empty - exception is silently swallowed
}
// ✅ CORRECT - At minimum, log it
try {
riskyOperation();
} catch (Exception e) {
logger.error("Operation failed", e);
// OR at minimum: e.printStackTrace();
}2. Using Exception Handling for Flow Control
// ❌ WRONG - Don't use exceptions for normal flow
try {
int value = Integer.parseInt(input);
} catch (NumberFormatException e) {
value = 0; // Using exception as an if-else
}
// ✅ CORRECT - Validate first
if (input != null && input.matches("\\d+")) {
int value = Integer.parseInt(input);
} else {
value = 0;
}3. Catching Too Broad an Exception
// ❌ WRONG - Too broad
try {
// many operations
} catch (Exception e) {
System.out.println("Something went wrong");
}
// ✅ CORRECT - Catch specific exceptions
try {
// many operations
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
} catch (IOException e) {
System.out.println("IO error: " + e.getMessage());
}Best Practices Summary
- Handle exceptions at the right level — don't catch too early or too late
- Be specific — catch the most specific exception type possible
- Never swallow exceptions — always log or re-throw
- Use finally for cleanup — close resources properly
- Prefer try-with-resources — for AutoCloseable objects (Java 7+)
- Document exceptions — use
@throwsin Javadoc - Don't use exceptions for flow control — they're expensive
Interview Questions
Q1: What is the difference between an Error and an Exception?
Answer: Errors are serious, unrecoverable problems (usually JVM-related like OutOfMemoryError) that applications should not catch. Exceptions are recoverable conditions that applications can and should handle. Both extend Throwable, but they serve different purposes.
Q2: What happens if an exception is not handled?
Answer: The JVM's default exception handler catches it, prints the exception details (name, message, stack trace) to System.err, and terminates the program abnormally.
Q3: Can we handle Errors in Java?
Answer: Technically yes (since Error extends Throwable, you can catch it), but you should NOT. Errors indicate severe problems that the application cannot reasonably recover from. Catching OutOfMemoryError, for example, doesn't guarantee the program can continue safely.
Q4: Why is exception handling important in real applications?
Answer: Without exception handling: (1) programs crash unpredictably, (2) resources leak (unclosed connections), (3) users see ugly stack traces, (4) partial operations leave data in inconsistent states. Exception handling ensures graceful degradation, proper cleanup, meaningful error messages, and application stability.
Q5: What is the difference between checked and unchecked exceptions?
Answer: Checked exceptions are verified by the compiler — you must handle or declare them (IOException, SQLException). Unchecked exceptions (subclasses of RuntimeException) are not checked at compile time — they indicate programming bugs (NullPointerException, ArrayIndexOutOfBoundsException).
Q6: Is NullPointerException a checked or unchecked exception?
Answer: Unchecked. It extends RuntimeException. The compiler doesn't force you to handle it because it's typically caused by a programming error that should be fixed in the code logic rather than caught.
Q8: What is the difference between compile-time and runtime exceptions?
A: Compile-time (checked) exceptions are verified by the compiler — you must handle them with try-catch or declare them with throws (e.g., IOException, SQLException). Runtime (unchecked) exceptions extend RuntimeException and are NOT checked at compile time — they indicate programming errors (e.g., NullPointerException, ArrayIndexOutOfBoundsException).
Q9: Can we prevent all exceptions from occurring?
A: No. While defensive programming reduces exceptions, some are unavoidable: network failures, disk full, out of memory, invalid user input. The goal isn't to prevent all exceptions but to handle them gracefully — log the error, clean up resources, notify the user, and continue or fail safely.
Q10: What happens to the call stack when an exception is thrown?
A: The JVM searches backward through the call stack for a matching catch block (exception propagation/unwinding). If found, execution continues in that catch block. If no handler is found all the way back to main(), the default exception handler prints the stack trace and terminates the thread.
Q11: Why is exception handling important in production applications?
A: (1) Prevents data corruption from half-completed operations, (2) Provides meaningful error messages to users, (3) Ensures resources (files, connections) are properly released, (4) Enables logging for debugging, (5) Allows graceful degradation instead of crashes, (6) Supports transaction rollback in databases.
Q12: What is the performance impact of exception handling?
A: The try block itself has negligible overhead. The EXPENSIVE part is when exceptions are actually thrown — creating the exception object captures the full stack trace (expensive), then stack unwinding occurs. This is why exceptions should never be used for normal control flow (like loop termination).
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Exception Handling Introduction.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Java Master Course topic.
Search Terms
java-master-course, java master course, java, master, course, exception, handling, introduction
Related Java Master Course Topics