1. Debugging and Logging
Every Java programmer spends time reading compiler errors, stack traces, and logs. These tools are part of the programming workflow, not signs that something unusual happened.
1.1. Compiler errors
Compiler errors happen before the program runs. They usually point to syntax problems, missing imports, type mismatches, or package layout problems.
error: cannot find symbol
Optional<String> name = Optional.of("John");
^
symbol: class Optional
In this case the code probably needs an import.
import java.util.Optional;
1.2. Runtime exceptions
Runtime exceptions happen while the program is running. The stack trace shows the exception type, the message, and the path through the code.
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.oneoffcoder.java.exception.DivideByZero.main(DivideByZero.java:8)
Start with the first line that points to your code. In this example, the useful
location is DivideByZero.java:8.
1.3. Printing values
The quickest debugging tool is often a temporary print statement.
int total = price * quantity;
System.out.println("total = " + total);
Print statements are useful while exploring, but they should not become the main way a production program reports status.
1.4. Assertions
Assertions document assumptions that should always be true while debugging.
int age = 23;
assert age >= 0 : "age must be non-negative";
Assertions are disabled by default. Enable them with -ea when running the
program.
java -ea com.oneoffcoder.java.SomeProgram
1.5. Basic logging
Java includes java.util.logging for simple logs.
import java.util.logging.Logger;
public class LoggingDemo {
private static final Logger LOGGER =
Logger.getLogger(LoggingDemo.class.getName());
public static void main(String[] args) {
LOGGER.info("program started");
}
}
Logs are better than print statements when a program runs for a long time, serves users, or needs different levels of detail in development and production.