Introduction to Exceptions in Java
Table of Contents + β
In the last lesson you learned about Java anonymous classes. Your code works fine in tests. Then a real user types a word where you expected a number, and the program stops dead with a wall of red text. That red text is an exception.
This lesson covers:
- What an exception is.
- What happens when you ignore one.
- How to read the error so you can fix it.
π€ What Is an Exception?
Think about real life. You are following a recipe step by step. Step four says βadd two eggs.β You open the fridge and there are no eggs. You cannot carry on as if nothing happened. That missing-egg moment is an exception. Your program hits the same kind of wall.
An exception is an event that breaks the normal flow of your program while it runs:
- It happens at runtime, not while you compile.
- The program was going line by line, then hit something it could not do.
- Instead of carrying on with wrong data, Java raises an exception.
- That is a good thing. Java tells you loudly that something went wrong.
These everyday things cause exceptions in Java:
- Dividing a whole number by zero. The math is impossible.
- Using a variable that points to nothing, then calling a method on it.
- Asking for the tenth item in an array that has only three.
- Trying to turn the text
"hello"into a number. - Reading a file that is not there.
π₯ What Happens If You Do Not Handle It?
When an exception happens and you do nothing about it:
- The program crashes. It stops right there.
- Every line after the problem is skipped.
- Java prints a block of text called a stack trace to explain what went wrong and where.
This program tries to divide a number by zero, which Java cannot do.
public class Main { public static void main(String[] args) { System.out.println("Starting the program..."); int a = 10; int b = 0; int result = a / b; // β cannot divide by zero System.out.println("Result is " + result); System.out.println("Program finished."); }}Here is what happens when you run it:
- The first line prints fine.
- It sets
ato 10 andbto 0. Still fine. - Then
a / bis 10 divided by 0. Impossible. Java throws an exception here. - Nothing catches it, so the program stops at once.
- The two
printlnlines below never run.
Output
Starting the program...Exception in thread "main" java.lang.ArithmeticException: / by zero at Main.main(Main.java:6)See how βResult isβ¦β and βProgram finished.β are missing? An unhandled exception ends your program early, whether you like it or not.
π How to Read a Stack Trace
That block of red text is really a friendly report. The first line tells you the problem:
Exception in thread "main" java.lang.ArithmeticException: / by zeroException in thread "main"means it happened in the main thread.java.lang.ArithmeticExceptionis the type of exception. Here it is a math problem./ by zerois the message. A short note on what went wrong.
The lines starting with at show the path to the error:
at Main.main(Main.java:6)- Each
atline is one step the program took to reach the error. - This one points to the
mainmethod, fileMain.java, line 6. - Read from the top. The top line is where the exception happened.
- The lines below show who called that code, step by step. That chain is the βstackβ.
Read the trace top down
The first at line points to the exact spot where the error happened. Start there. Open that file, go to that line number, and you are looking right at the problem. You almost never need to read the whole trace to fix a bug.
π³ The Exception Hierarchy
Every error and exception in Java is an object, and they share one common ancestor:
- At the top sits Throwable. The name means βsomething that can be thrown.β
- Under it the family splits into Error and Exception.
- Error covers serious problems you cannot recover from, like running out of memory. You leave these alone.
- Exception covers problems your code can deal with. This is the branch you work with.
- Under Exception sits RuntimeException and everything below it.
Here is the family as a table:
| Class | What it covers | Example |
|---|---|---|
| Throwable | The root of everything that can be thrown | (parent of all below) |
| Error | Serious failures you do not handle | OutOfMemoryError |
| Exception | Problems your code can handle | IOException |
| RuntimeException | A kind of Exception caused by bugs in logic | NullPointerException |
Keep that picture in your head. It explains the next idea.
β Checked vs Unchecked Exceptions
Java sorts exceptions into two groups, based on whether the compiler forces you to deal with them:
- A checked exception is one the compiler checks for. Java will not let you compile until you handle it or declare it.
IOExceptionis the classic example. - An unchecked exception is one the compiler does not force you to handle. These are everything under
RuntimeException, like dividing by zero or using a null value. - Unchecked exceptions usually come from bugs in your logic. So Java trusts you to write correct code.
- Simple rule: anything under
RuntimeExceptionis unchecked. Everything else underExceptionis checked.Erroryou leave alone.
An easy way to tell them apart
Checked exceptions are about things outside your control, like a missing file or a broken network. Java wants you to have a plan for them. Unchecked exceptions are usually programming mistakes, like a null value or a bad array index. Fix the bug and they go away.
π Common Built-in Exceptions
You will meet a handful of built-in exception types over and over. Here is each one with a tiny example of what triggers it.
ArithmeticException happens when the math is impossible, most often integer division by zero.
int x = 5 / 0; // β throws ArithmeticException: / by zeroNullPointerException happens when a variable points to nothing, but you use it as if it points to a real object. Here name holds nothing, yet we call length().
String name = null;int n = name.length(); // β throws NullPointerExceptionArrayIndexOutOfBoundsException happens when you ask for a spot that is not there. An array of three items has valid spots 0, 1, and 2.
int[] nums = {10, 20, 30};System.out.println(nums[5]); // β throws ArrayIndexOutOfBoundsExceptionNumberFormatException happens when text cannot become a number. The word "hello" is not a number.
int value = Integer.parseInt("hello"); // β throws NumberFormatExceptionIOException is a checked exception for failed input or output, like reading a file that does not exist. Because it is checked, the compiler makes you handle it.
Here is the array case as a full program, so you can see the real crash output.
public class Main { public static void main(String[] args) { System.out.println("About to read an array..."); int[] nums = {10, 20, 30}; System.out.println(nums[5]); // β index 5 does not exist System.out.println("This line never runs."); }}Output
About to read an array...Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3 at Main.main(Main.java:5)The message names the index you asked for, the length, and the exact line. Everything you need to fix it is right there.
π‘οΈ A First Look at Handling Them
You do not have to let an exception end everything. You can catch it and decide what to do instead:
- Put the risky code inside a
tryblock. - Put the recovery code inside a
catchblock. - If the risky code throws, control jumps to the catch instead of crashing.
Here is a quick taste. You will learn it fully in the next lesson.
public class Main { public static void main(String[] args) { try { int result = 10 / 0; // risky line System.out.println(result); } catch (ArithmeticException e) { System.out.println("Cannot divide by zero. Using 0 instead."); // β
recover } System.out.println("Program keeps running."); }}The division still fails. But this time we catch it. So instead of a stack trace and a dead program, we print a friendly message and carry on.
Output
Cannot divide by zero. Using 0 instead.Program keeps running.The program survived. The final line ran.
β οΈ Common Mistakes
Two habits get people into trouble fast.
Swallowing an exception silently. You catch it but do nothing inside the catch. Now the program runs with a hidden problem and no clue anything went wrong.
// β silent swallow: you will never know it failedtry { int n = Integer.parseInt(userInput);} catch (NumberFormatException e) { // empty, nothing here}
// β
at least report what happenedtry { int n = Integer.parseInt(userInput);} catch (NumberFormatException e) { System.out.println("That was not a valid number: " + e.getMessage());}Catching everything with one giant net. The broad Exception type hides what really went wrong and hides bugs you never meant to handle.
// β too broad: catches problems you did not plan for and hides themtry { process();} catch (Exception e) { System.out.println("Something broke");}
// β
catch the specific type you actually expecttry { process();} catch (NumberFormatException e) { System.out.println("Bad number input: " + e.getMessage());}β Best Practices
- Read the stack trace first. Start at the top line. It names the type, the message, the file, and the line. Most bugs are solved right there.
- Catch the specific type you expect. Catch
NumberFormatExceptionfor bad numbers, not the broadException. Specific catches make your intent clear. - Never swallow an exception silently. At the very least, print a message so you know it happened.
- Let serious Errors crash. Things like out-of-memory are not yours to fix at runtime. Do not try to catch
Error. - Prefer prevention where you can. Many unchecked exceptions, like a null value or a bad index, are bugs. Fixing the logic is better than catching the symptom.
π§© What Youβve Learned
Great start. Letβs recap.
- β An exception is an event that disrupts the normal flow of your program at runtime, like dividing by zero or using a null value.
- β If you do not handle it, the program crashes, skips the rest of the code, and prints a stack trace.
- β A stack trace tells you the exception type, a message, and the exact file and line. Read it from the top.
- β Everything throwable descends from Throwable, which splits into Error and Exception, with RuntimeException under Exception.
- β Checked exceptions are forced on you by the compiler. Unchecked ones, under RuntimeException, are not.
- β Common types include ArithmeticException, NullPointerException, ArrayIndexOutOfBoundsException, NumberFormatException, and IOException.
Check Your Knowledge
Test what you learned. Pick an answer for each question, then click Check.
- 1
What is an exception in Java?
Why: An exception is a runtime event that interrupts the normal flow, such as dividing by zero or using a null value.
- 2
What happens if an exception is not handled?
Why: An unhandled exception stops the program early, skips the rest of the code, and prints a stack trace.
- 3
Which class sits at the very top of the exception hierarchy?
Why: Throwable is the root. Error and Exception both extend it.
- 4
Which exception type is unchecked?
Why: NullPointerException extends RuntimeException, so it is unchecked. IOException and FileNotFoundException are checked.
π Whatβs Next?
Now you know what an exception is and how to read one when it crashes your program. The next step is learning how to stop that crash and recover gracefully. That is the job of the try-catch block, the single most important tool in exception handling. Letβs learn it properly.