Java Exception Handling
In this lesson
Things go wrong: a user types “abc” instead of a number, a file is missing, the network drops. Without handling, Java prints a scary stack trace and the program stops. Exception handling lets you catch the problem and respond gracefully.
What an exception looks like#
public class Crash {
public static void main(String[] args) {
int[] marks = {80, 90};
System.out.println(marks[5]);
System.out.println("This never prints");
}
}
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 2
at Crash.main(Crash.java:4)
Read stack traces from the top: the exception type, the message, then where it happened (file and line).
try and catch#
Put risky code in try; handle problems in catch. Step through the animation and try ten / 2 and 10 / 2 too:
public class SafeDivide {
public static void main(String[] args) {
String[] inputs = {"10", "abc", "0"};
for (String s : inputs) {
try {
int n = Integer.parseInt(s);
System.out.println("100 / " + n + " = " + (100 / n));
} catch (NumberFormatException e) {
System.out.println("'" + s + "' is not a number");
} catch (ArithmeticException e) {
System.out.println("Can't divide by zero");
} finally {
System.out.println("-- checked " + s);
}
}
}
}
100 / 10 = 10
-- checked 10
'abc' is not a number
-- checked abc
Can't divide by zero
-- checked 0
- When an exception happens, Java skips the rest of the try and jumps to the first matching
catch. finallyruns always: success, exception, even afterreturn. Use it for cleanup.- Catch several types in one block with
|:catch (NumberFormatException | ArithmeticException e).
The exception family tree#
Throwable
โโโ Error (serious JVM problems: OutOfMemoryError, StackOverflowError; don't catch)
โโโ Exception
โโโ IOException, SQLException, ... โ checked
โโโ RuntimeException โ unchecked
โโโ NullPointerException
โโโ ArithmeticException
โโโ ArrayIndexOutOfBoundsException
โโโ NumberFormatException (via IllegalArgumentException)
โโโ IllegalStateException
Checked vs unchecked#
| Checked | Unchecked (RuntimeException) | |
|---|---|---|
| Examples | IOException, SQLException | NullPointerException, IllegalArgumentException |
| Compiler forces handling? | Yes: catch it or declare throws | No |
| Usually means | something outside your control failed | a bug or invalid input |
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class ReadFile {
static String load(String file) throws IOException { // "I might throw this"
return Files.readString(Path.of(file));
}
public static void main(String[] args) {
try {
System.out.println(load("notes.txt"));
} catch (IOException e) {
System.out.println("Could not read file: " + e.getMessage());
}
}
}
throw: raise your own exception#
static void withdraw(double balance, double amount) {
if (amount <= 0) {
throw new IllegalArgumentException("Amount must be positive");
}
if (amount > balance) {
throw new IllegalStateException("Insufficient balance");
}
System.out.println("Withdrawn " + amount);
}
throw(singular, inside a method) raises an exception.throws(plural, in the method signature) declares what might be thrown.
Custom exceptions#
Create meaningful exceptions for your domain:
public class InsufficientFundsException extends Exception {
private final double shortBy;
public InsufficientFundsException(double shortBy) {
super("Insufficient funds, short by โน" + shortBy);
this.shortBy = shortBy;
}
public double getShortBy() { return shortBy; }
}
Extend Exception for checked, RuntimeException for unchecked. Most modern frameworks (like Spring) prefer unchecked exceptions.
try-with-resources#
Files, database connections and network sockets must be closed. try (...) closes them automatically, even on error:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class FirstLine {
public static void main(String[] args) {
try (BufferedReader reader = new BufferedReader(new FileReader("data.txt"))) {
System.out.println(reader.readLine());
} catch (IOException e) {
System.out.println("Problem: " + e.getMessage());
} // reader.close() is called automatically
}
}
Any class implementing AutoCloseable works here.
Best practices#
- Catch specific exceptions, not
ExceptionorThrowable. - Never swallow exceptions silently:
catch (Exception e) {}hides bugs. At least log them. - Validate early: check inputs and throw
IllegalArgumentExceptionwith a clear message. - Don’t use exceptions for normal flow (like ending a loop). They’re slower and confusing.
- Keep the cause when wrapping:
throw new ServiceException("Save failed", e);.
NullPointerException is the most common Java exception. Avoid it by checking for null, using Objects.requireNonNull, returning empty lists instead of null, or Optional (Streams lesson). Java 14+ even tells you exactly which variable was null.
Common mistakes#
- Catching
Exceptionbefore a more specific one (compile error: already caught). - Using
finallytoreturna value (it overrides the try’s return or hides exceptions). - Forgetting to close resources (use try-with-resources).
Exercise#
- Read two numbers as Strings, divide them, and handle bad numbers and division by zero with clear messages.
- Write
validateAge(int age)that throwsIllegalArgumentExceptionif age is negative or above 150. - Create a checked
InvalidMarksExceptionand throw it when marks are outside 0-100. - What does this print?
try { return 1; } finally { System.out.println("finally"); }
Hint for 4
It prints “finally” and then the method returns 1. finally runs before the method actually returns.
Interview corner#
- Checked vs unchecked? Checked must be caught or declared (compile-time check); unchecked extends RuntimeException and doesn’t.
- throw vs throws?
throwraises an exception object;throwsdeclares it in the signature. - Does finally always run? Almost: except if the JVM exits (
System.exit) or crashes. - Error vs Exception? Errors are serious JVM problems you shouldn’t catch; exceptions are conditions your program can handle.
- What is try-with-resources? A try that automatically closes
AutoCloseableresources.
Summary#
tryrisky code,catchspecific exceptions,finallyfor cleanup.- Checked exceptions must be handled or declared; unchecked usually signal bugs.
throwyour own exceptions with clear messages; create custom ones for your domain.- try-with-resources closes files and connections automatically.
Next: lambdas and streams, modern Java’s way to process data.
Quick quiz
3 questions. Check what stuck and earn 2 XP for each right answer.
Progress is saved in this browser. Create a free account to keep it on every device.
Get new lessons in your inbox
One email when we publish a new tutorial or guide. No spam, unsubscribe in one click.