Introduction to Exceptions in Java

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 a to 10 and b to 0. Still fine.
  • Then a / b is 10 divided by 0. Impossible. Java throws an exception here.
  • Nothing catches it, so the program stops at once.
  • The two println lines 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 zero
  • Exception in thread "main" means it happened in the main thread.
  • java.lang.ArithmeticException is the type of exception. Here it is a math problem.
  • / by zero is 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 at line is one step the program took to reach the error.
  • This one points to the main method, file Main.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. IOException is 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 RuntimeException is unchecked. Everything else under Exception is checked. Error you 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 zero

NullPointerException 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 NullPointerException

ArrayIndexOutOfBoundsException 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 ArrayIndexOutOfBoundsException

NumberFormatException happens when text cannot become a number. The word "hello" is not a number.

int value = Integer.parseInt("hello"); // ❌ throws NumberFormatException

IOException 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 try block.
  • Put the recovery code inside a catch block.
  • 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 failed
try {
int n = Integer.parseInt(userInput);
} catch (NumberFormatException e) {
// empty, nothing here
}
// βœ… at least report what happened
try {
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 them
try {
process();
} catch (Exception e) {
System.out.println("Something broke");
}
// βœ… catch the specific type you actually expect
try {
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 NumberFormatException for bad numbers, not the broad Exception. 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. 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. 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. 3

    Which class sits at the very top of the exception hierarchy?

    Why: Throwable is the root. Error and Exception both extend it.

  4. 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.

Java try-catch Block

Share & Connect