Exercise 2.2: Error Handling and Debugging

Author

Chuck Nelson

Published

October 15, 2025

1 Purpose

The purpose of this exercise is to introduce the fundamental concepts of error handling and debugging in Java. No program is perfect, and a crucial skill for any developer is to be able to identify, understand, and fix errors. You will learn the difference between compilation and runtime errors, understand what exceptions are, and use try...catch blocks to handle them gracefully.

2 What You’ll Accomplish

By the end of this exercise, you will have successfully:

  • Identified and corrected common compilation errors.
  • Intentionally created and analyzed runtime errors to understand their cause.
  • Explained the concept of an Exception in Java.
  • Used a try...catch block to prevent a runtime exception from crashing your program.
  • Handled common built-in exceptions like NullPointerException and ArrayIndexOutOfBoundsException.

This exercise maps to the following program and course learning outcomes:

  • Program Learning Outcomes (PLOs):
    • 3. Apply concepts: You will apply core programming concepts related to error handling and program flow.
    • 5. Implement solutions: You will implement code that correctly anticipates and manages errors.
  • Course Learning Outcomes (CLOs):
    • 1. Develop algorithmic solution: You will modify your code to handle alternative (error) pathways.
    • 6. Debug and test programs: This exercise is entirely focused on debugging and handling errors.

This exercise aligns with the O*NET SOC Code 15-1251.00 for Computer Programmers.

Learning Objective O*NET KSAs Technologies Used
Differentiate between compilation and runtime errors. Knowledge: Computers and Electronics
Skills: Troubleshooting
Development environment software: VS Code, JDK
Implement try...catch blocks to handle exceptions. Knowledge: Programming
Skills: Programming, Critical Thinking
Object or component oriented development software: Java
Debug common exceptions like NullPointerException. Skills: Troubleshooting, Debugging Development environment software: Java, VS Code Terminal

3 Understanding Errors

In programming, an error, often called a “bug,” is a mistake in the code that causes it to behave in an unexpected way or to stop running altogether. Learning to “debug” (find and fix bugs) is a core part of being a programmer. There are two main categories of errors you will encounter in a compiled language like Java.

Compilation Errors

A compilation error (or syntax error) is a mistake that violates the rules of the Java language. The Java compiler (javac) will find these errors when you try to build your project. Your code will not compile, and no .class file will be created, until you fix them.

Common examples include: - Forgetting a semicolon (;) at the end of a line. - A typo in a variable name or keyword (e.g., Sytem.out.println instead of System.out.println). - Mismatched brackets ({ or (). - Trying to assign a value of the wrong type to a variable (e.g., int x = "hello";).

NoteProactive Error Checking with VS Code

You don’t always have to wait for compilation to find basic errors. Modern IDEs like Visual Studio Code have built-in support for linters.

A linter is a tool that analyzes your source code as you type to flag potential programming errors, stylistic errors, and suspicious constructs. In VS Code, these are often highlighted with red squiggly underlines, and a summary of all detected issues is available in the “Problems” pane (usually found in the bottom panel, or accessible via View > Problems) and also with the Ctrl+Shift+M keyboard shortcut.

This provides immediate feedback, helping you fix syntax errors and other common mistakes long before you even try to compile your code.

Runtime Errors

A runtime error occurs while your program is running. The code is syntactically correct and compiled successfully, but something unexpected happens during execution that the program doesn’t know how to handle. In Java, most runtime errors result in an Exception.

When an exception occurs, the Java Virtual Machine (JVM) creates an Exception object that contains information about the error, including where it happened. If this exception is not “caught” (handled), the program will terminate and print a “stack trace” to the console, which helps you find the source of the error.

4 Your Task: Let’s Break Things

The best way to learn about errors is to cause them intentionally. In this exercise, you will use the App.java file from the previous exercises to create and fix several common errors.

Scenario 1: The Null Pointer

A NullPointerException is one of the most common runtime errors in Java. It happens when you try to use a variable that holds the value null as if it were pointing to a real object with methods.

  1. Modify App.java: Open your App.java file. Inside the main method, add the following lines. We’ll declare a String variable but assign it the value null.

    String text = null;
    System.out.println("The length of the text is: " + text.length());
  2. Compile and Run: Open the integrated terminal and compile your code with mvn clean compile. It should compile successfully because there are no syntax errors. Now, run the application with mvn exec:java.

  3. Analyze the Crash: Your program will crash and you will see a NullPointerException with a stack trace. Notice how the stack trace tells you the exact line number where the error occurred because you tried to call the .length() method on a null reference.

  4. Fix the Error: To fix this, you must ensure the variable is not null before you use it. For now, just remove the two lines you added. In a real application, you would add a check like if (text != null).

TipDid You See the Warning?

Remember the linter and the “Problems” pane we discussed earlier? If you look at the line text.length() in VS Code, you should see a yellow squiggly underline.

If you hover over it or check the Problems pane, you will see a warning like: “Null pointer access: The variable text can only be null at this location”. This is the linter proactively warning you that you are trying to use a variable that might be null, which could lead to a runtime error. This is a powerful feature that helps you catch potential bugs before you even run your program!

Scenario 2: Out of Bounds

An ArrayIndexOutOfBoundsException occurs when you try to access an array element using an index that doesn’t exist. For example, if an array has 3 elements (at indices 0, 1, and 2), trying to access index 3 will cause this error.

  1. Modify App.java: Inside the main method, add the following lines. The args array holds command-line arguments. Unless you provide some when you run the program, its length is 0.

    System.out.println("First command-line argument: " + args[0]);
  2. Compile and Run: Compile with mvn clean compile and run with mvn exec:java.

  3. Analyze the Crash: The program will crash with an ArrayIndexOutOfBoundsException.

  4. Fix the Error: Remove the line you added. A proper fix would be to check the length of the array first: if (args.length > 0).

TipStatic vs. Dynamic Analysis

You might wonder why the linter caught the potential NullPointerException but not this ArrayIndexOutOfBoundsException.

The linter performs static analysis, meaning it analyzes your code without actually running it. It could see that the text variable was assigned null and never changed, so it could predict the error.

However, the contents of the args array are determined at runtime (when the user runs the program), not at compile time. The linter has no way of knowing what a user will provide as command-line arguments, so it cannot warn you that args[0] might not exist.

This is why you should almost always perform a bounds check before accessing an array element, especially if the array’s size can change. Try it!

// Good Practice: Check the array length before access
if (args.length > 0) {
    System.out.println("First argument: " + args[0]);
} else {
    System.out.println("No command-line arguments were provided.");
}

5 Handling Exceptions with try...catch

Crashing is not very user-friendly. Instead of letting the program terminate, we can “catch” the exception and handle it gracefully. We do this using a try...catch block.

  • try block: You place the code that might cause an exception inside the try block.
  • catch block: If an exception occurs in the try block, the JVM immediately jumps to the catch block. The code in the catch block is then executed.

Scenario 3: Graceful Handling

Let’s repeat Scenario 1, but this time, we’ll catch the exception.

  1. Modify App.java: Wrap the code that caused the NullPointerException in a try...catch block.

    String text = null;
    try {
        // This line might cause a NullPointerException
        System.out.println("The length of the text is: " + text.length());
    } catch (NullPointerException e) {
        // This block runs ONLY if a NullPointerException occurs
        System.out.println("Error: Cannot measure the length of a non-existent string.");
        // The 'e' variable holds the exception object. We can print its stack trace for debugging.
        // e.printStackTrace(); 
    }
    System.out.println("Program continues after the error.");
  2. Compile and Run: Compile and run your code again.

  3. Analyze the Output: Notice that the program no longer crashes! It prints your custom error message and then continues to the final println statement. This is the power of exception handling—it allows you to control the flow of your program even when errors occur.

6 Reflect and Review

ImportantReflection: 3-2-1

In your Microsoft Teams Student Notebook, answer the following:

  • 3 differences between a compilation error and a runtime error.
  • 2 reasons why you would use a try...catch block.
  • 1 question you still have about exceptions.
TipCheck on Learning

Answer the following questions in your Microsoft Teams Student Notebook.

  1. If your Java code has a syntax error, what happens when you run mvn clean compile?
  2. What is a “stack trace” and why is it useful?
  3. What is the purpose of the catch block in a try...catch statement?
  4. Besides NullPointerException and ArrayIndexOutOfBoundsException, find and name one other common built-in Java exception.
Back to top