Skip to Content
Course content

170: Debugging Java Applications in an IDE

Click on the "Edit" button in the top corner of the screen to edit your slide content.

You've probably spent hours staring at a block of code that looks logically perfect, yet the output is stubbornly wrong. Your first instinct is usually to sprinkle System.out.println() calls everywhere to "see what's happening." I did that for years, but it's a slow, messy process that litters your codebase with junk you have to delete later. If you're using a modern IDE like IntelliJ, Eclipse, or VS Code, you have a superpower called the Debugger. It lets you pause time and poke around inside your program's memory while it's actually running.

Let's look at a piece of code that is behaving badly. Imagine we're building a simple GradeBook system. We have a method that calculates the average of a student's scores, but it's giving us the wrong result.

public class GradeBook {
    public double calculateAverage(java.util.List<Integer> grades) {
        int sum = 0;
        for (int i = 0; i < grades.size(); i++) {
            sum += grades.get(i);
        }
        return sum / grades.size(); 
    }

    public static void main(String[] args) {
        GradeBook gb = new GradeBook();
        java.util.List<Integer> myGrades = java.util.Arrays.asList(80, 85, 90, 82);
        // Expected: 84.25
        System.out.println("Average: " + gb.calculateAverage(myGrades));
    }
}

When you run this, you get Average: 84.0. You're expecting 84.25. At a glance, the loop is fine, the sum is adding up, and the division is happening. Why is the decimal gone?

The Truncated Average Mystery

If we just look at the code, we might assume the sum is wrong. But instead of guessing, we use a breakpoint. In your IDE, you click the gutter (the space next to the line number) on the return line. This tells the JVM: "Run normally until you hit this line, then freeze everything."

When you run this in "Debug Mode," the IDE pauses. Now, you can look at the Variables View. You'll see that sum is 337 and grades.size() is 4. Both are correct. The math 337 divided by 4 is definitely 84.25. So why is the result 84.0?

This is where the debugger saves you. You can highlight the expression sum / grades.size() in the IDE's "Evaluate Expression" tool. You'll see that Java is performing integer division. Because both sum and grades.size() are integers, Java throws away the remainder before the result is even cast to a double for the return type.

Stopping the Precision Loss

The fix is simple: we need to tell Java that we want this division to happen in floating-point math, not integer math. We can do this by casting one of the operands to a double.

public double calculateAverage(java.util.List<Integer> grades) {
    int sum = 0;
    for (int i = 0; i < grades.size(); i++) {
        sum += grades.get(i);
    }
    // By casting sum to double, Java promotes the entire operation to double precision
    return (double) sum / grades.size(); 
}

Now, when you run the debugger again and evaluate that expression, you'll see 84.25. I want you to get comfortable with three specific debugger actions: Step Over (go to the next line), Step Into (dive inside a method call), and Step Out (finish the current method and go back to the caller). Using these, you can trace the exact path of execution and catch logic errors that are nearly invisible to the naked eye.

Navigating the Call Stack

One more thing I've found invaluable: the Call Stack. When you're paused at a breakpoint, the IDE shows you exactly how you got there. If you're inside calculateAverage, the stack will show that main called it. In a real-world app with twenty layers of method calls, the Call Stack is the only way to figure out who passed a null value into your method three levels down the chain. Don't just look at the current line; look at the path that led you there.




📋 Practical Task

Exercise: Fixing the Inventory Ledger Leak

You are maintaining a warehouse system. There is a bug in the processInventory method where the final count of items is consistently lower than it should be. The developer who wrote it used a loop that seems correct, but the totals are wrong.

Your Task: 1. Copy the following code into your IDE. 2. Set a breakpoint inside the for loop. 3. Use the debugger to inspect the currentStock variable during each iteration. 4. Identify why the total is incorrect (Hint: Look closely at how the loop index is being handled or how the value is being updated). 5. Fix the bug so that the final output for the given input is Total Stock: 155.

import java.util.*;

public class WarehouseManager {
    public static void main(String[] args) {
        int[] shipments = {50, 30, 40, 35}; 
        int currentStock = 0;

        // BUG: The logic here is slightly flawed. 
        // Use your debugger to see what's happening to the index or the sum.
        for (int i = 0; i < shipments.length; i++) {
            if (i == 2) {
                // Imagine a logic error where a shipment is skipped or handled wrong
                continue; 
            }
            currentStock += shipments[i];
        }

        System.out.println("Total Stock: " + currentStock); 
        // Expected: 155, Actual: 115
    }
}
Rating
0 0

There are no comments for now.

to be the first to leave a comment.