How to Solve Java Problems

August 18, 20265 min readUpdated 8/20/2026

Everyone gets stuck. The difference between an hour and a day is having a method instead of guessing. This post is that method — four steps, in order — plus the errors every Java beginner hits and what each one is really telling you.

1. Read the error. Actually read it.

The most common mistake is pasting an error into a search engine before reading it. Java's messages are specific, and modern ones frequently contain the entire answer:

Cannot invoke "String.length()" because "customer.name" is null

That names the expression, the field, and what was attempted. No search needed. Before you look anything up, answer three questions from the message alone:

  • What type of failure is it? A compile error means the code is not valid Java. A runtime exception means it ran and hit something unexpected. These need completely different responses.
  • Which line is mine? Read down the stack trace to the first frame in your own package.
  • Is there a Caused by? If so, the last one is the real failure. See Debugging.

2. Reproduce it smaller

A bug inside a 400-line service with a database and three HTTP calls is nearly impossible to reason about. Shrink it until it is not:

class Isolate {
    // Instead of debugging this inside the whole request pipeline...
    void run() {
        // ...reproduce just the failing step, with a hardcoded input
        String input = "2026-13-45";                 // the value that broke production
        try {
            LocalDate.parse(input);
        } catch (DateTimeParseException e) {
            System.out.println("reproduced: " + e.getMessage());
        }
    }
}

Write it as a test rather than a scratch main. You get a reproduction you can run in one second, and when you fix it you have a regression test for free.

If you cannot reproduce it, you do not yet understand it — and a fix you cannot verify is a guess. Getting a reliable reproduction is usually most of the work.

3. Change one thing at a time

When something does not work, the temptation is to change four things and re-run. If it then works you have learned nothing, and you are probably carrying three unnecessary changes.

Change one thing. Run. Observe. This is slower for about ten minutes and much faster after that.

The same discipline applies to what you keep: if a change did not help, undo it before trying the next one. Code that accumulates failed attempts becomes its own second problem.

4. Check your assumptions

When the first three steps have not cracked it, the bug is almost always hiding inside something you are certain about. Write down what you believe, then verify each item:

  • "The list has items in it."
  • "This method is being called."
  • "The config value was loaded."
  • "The value is what the database contains."
class Check {
    void process(List<String> orders, String region) {
        // Prove the assumptions rather than trusting them
        System.out.println("orders=" + orders.size() + " region=" + region);

        if (orders.isEmpty()) {
            System.out.println("the loop below never runs — this is probably the bug");
        }

        for (String order : orders) {
            System.out.println("processing " + order);
        }
    }
}

Two specific things worth verifying early, because they cause bugs that look impossible: are you comparing objects with == where you needed equals, and is the code running the version you just edited? A stale build explains a surprising share of "my change had no effect".

The errors every beginner hits

MessageWhat it meansUsual cause
cannot find symbola name that does not exist heretypo, missing import, or a variable out of scope
incompatible typeswrong type on one sidea missing cast, or int where you needed double
variable might not have been initializedread before assigneda local declared but only set inside an if
missing return statementa path that returns nothingan if with no else at the end of a method
unreported exceptiona checked exception ignoredcatch it or declare throws
class X is public, should be declared in a file named X.javaexactly thatthe file name does not match the class
could not find or load main classthe JVM cannot locate itwrong classpath, or the package was left off the run command
non-static variable cannot be referenced from a static contextan instance field used from mainmake it static, or create an object

The last one catches nearly everyone in their first week — see static and final for why.

Searching well

When you do search, the shape of the query matters:

  • Search the exception type and the message, not your variable names. Strip out anything specific to you — OrderService, customerId — or you will find nothing.
  • Add the library and version. "spring boot 4" finds different answers from "spring".
  • Check the date. Java advice ages badly. An answer that predates 2014 will show you Date, Vector and raw types — see Introduction to Java.
  • Read the official documentation. The Javadoc for the class you are using is frequently faster than a search result and is never out of date.

If you use an AI assistant, the same rule applies as to any answer: run it before you believe it. Confidently wrong Java compiles about as often as it does not.

Asking for help properly

A good question gets an answer in minutes; a vague one gets nothing. Include four things:

  1. What you are trying to do — one sentence.
  2. The smallest code that shows the problem — from step 2, which you already have.
  3. The full error, including every Caused by. Not a paraphrase, not a screenshot of half of it.
  4. What you already tried and what happened.

Writing that out solves the problem often enough to be a technique in its own right — the act of explaining it forces you through steps 1 to 4 in order.

Next

Java best practices is next — the habits that stop these problems being created in the first place.