Debugging Strategy
Before you start fixing bugs, take a few minutes to read through this page. Debugging is a skill, and like any skill, it improves when you follow a consistent process. The strategy below is the same approach professional developers use. Practice it here and you will be ready to apply it in Lab 9, Project 1, and beyond.
Fix Errors in the Correct Order
Not all errors are equal. Work through them in this order:
- Compiler errors first. The program cannot run until it compiles, so there is no point chasing runtime or logic problems yet. Fix every compiler error before moving on.
- Runtime errors second. Once the program compiles and runs, look for crashes or exceptions. Resolve these before evaluating output.
- Logic errors last. Only after the program runs without crashing should you compare the output to the expected result and hunt for incorrect behavior.
This order matters because each layer depends on the one before it. Skipping ahead wastes time on problems that may disappear once earlier errors are resolved.
Read Error Messages Carefully
Error messages are your first clue, not an obstacle. Each one typically tells you:
- The error type (what went wrong)
- The file name (where it happened)
- The line number (exactly where to look)
Start at the reported location before looking anywhere else. Resist the urge to scan the whole file or start changing things at random.
Reading a Stack Trace
When a runtime error occurs, Java prints a stack trace. Here is how to interpret it:
- The first line names the exception type, which tells you what kind of error occurred (for example,
NullPointerExceptionorArrayIndexOutOfBoundsException). - The lines below show the call stack, which is the sequence of method calls that led to the crash.
- Find the first line that points to your own code (not a Java library class). That is almost always the best place to start investigating.
Example:
Exception in thread "main" java.lang.NullPointerException
at TrailBuilder.loadTrails(TrailBuilder.java:42)
at Launcher.main(Launcher.java:10)
In this example, start at TrailBuilder.java, line 42. That is where your code triggered the error.
Fix One Problem at a Time
After identifying an error, make one focused change, then recompile and rerun. Do not fix multiple issues at once before testing.
Why this matters:
- One fix can resolve several reported errors at the same time. If you made five changes and things break, you will not know which change caused the new problem.
- Testing after every change keeps you in control of what is happening.
This approach takes discipline, but it saves time in the long run.
Use Print Statements Strategically
When behavior is unexpected and you are not sure why, add System.out.println() statements to investigate. Use them to:
- Display variable values at key points in the program
- Confirm that a method was actually called
- Trace the flow of the program to find where behavior changes
- Verify assumptions about what data looks like at a given moment
Think of print statements as asking the program questions. You are not guessing. You are gathering evidence.
Remove or comment out debugging print statements before submitting your final work.
Connecting This to Project 1
Project 1 contains the same categories of errors you will fix in Lab 9: compiler errors, runtime errors, and logic errors. The process you practice here is exactly the process you will use there.
The goal is not just to complete the lab. The goal is to build a debugging workflow you can rely on every time you encounter a problem. That is what professional developers do.