Best Practices for Exception Handling in Java

This article outlines essential Java exception‑handling best practices, covering resource cleanup with finally or try‑with‑resources, declaring specific exceptions, documenting throws clauses, providing descriptive messages, catching the most specific exceptions first, avoiding catching Throwable, never ignoring or double‑logging exceptions, and correctly wrapping exceptions without losing the original cause.

Top Architect
Top Architect
Top Architect
Best Practices for Exception Handling in Java

Handling exceptions in Java is not trivial; even experienced developers need clear guidelines on which exceptions to handle and how. Many development teams establish their own rules, which often differ from each other.

This article presents several widely adopted best practices for exception handling.

Clean up resources in a finally block or use try‑with‑resources

When working with resources such as InputStream that must be closed, a common mistake is to close the resource inside the try block. If an exception occurs before the close call, the resource will not be released.

public void doNotCloseResourceInTry() {
    FileInputStream inputStream = null;
    try {
        File file = new File("./tmp.txt");
        inputStream = new FileInputStream(file);
        // use the inputStream to read a file
        // do NOT do this
        inputStream.close();
    } catch (FileNotFoundException e) {
        log.error(e);
    } catch (IOException e) {
        log.error(e);
    }
}

The proper approach is to place all cleanup code in a finally block or to use the try‑with‑resources statement.

public void closeResourceInFinally() {
    FileInputStream inputStream = null;
    try {
        File file = new File("./tmp.txt");
        inputStream = new FileInputStream(file);
        // use the inputStream to read a file
    } catch (FileNotFoundException e) {
        log.error(e);
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                log.error(e);
            }
        }
    }
}

public void automaticallyCloseResource() {
    File file = new File("./tmp.txt");
    try (FileInputStream inputStream = new FileInputStream(file)) {
        // use the inputStream to read a file
    } catch (FileNotFoundException e) {
        log.error(e);
    } catch (IOException e) {
        log.error(e);
    }
}

Specify concrete exceptions

Declare the most specific exception types in method signatures so that the code is easier to understand.

public void doNotDoThis() throws Exception {
    ...
}

public void doThis() throws NumberFormatException {
    ...
}

For example, NumberFormatException clearly indicates a numeric format error.

Document exceptions

When a method declares that it throws an exception, add Javadoc comments describing the circumstances under which the exception is thrown. This provides callers with valuable information.

/**
 * This method does something extremely useful ...
 *
 * @param input
 * @throws MyBusinessException if ... happens
 */
public void doSomething(String input) throws MyBusinessException {
    ...
}

Include descriptive information when throwing

When throwing an exception, include a concise description of the problem. The exception class name already conveys the type, so a short message is sufficient.

try {
    new Long("xyz");
} catch (NumberFormatException e) {
    log.error(e);
}
NumberFormatException

tells you the error is a format issue; the additional message can provide the offending value.

Catch the most specific exception first

Catching a generic exception before a specific one prevents the specific catch block from ever executing. Always order catch blocks from most specific to most general.

public void catchMostSpecificExceptionFirst() {
    try {
        doSomething("A message");
    } catch (NumberFormatException e) {
        log.error(e);
    } catch (IllegalArgumentException e) {
        log.error(e);
    }
}

Never catch Throwable

Throwable

is the superclass of all errors and exceptions. Catching it also captures serious JVM errors that should not be handled. Avoid catching Throwable unless you have a very specific reason.

public void doNotCatchThrowable() {
    try {
        // do something
    } catch (Throwable t) {
        // don't do this!
    }
}

Never ignore exceptions

Do not write empty catch blocks or assume an exception will never happen. Always at least log the exception so that unexpected problems can be diagnosed.

public void doNotIgnoreExceptions() {
    try {
        // do something
    } catch (NumberFormatException e) {
        // this will never happen
    }
}

In practice, unexpected exceptions do occur; logging them provides essential debugging information.

public void logAnException() {
    try {
        // do something
    } catch (NumberFormatException e) {
        log.error("This should never happen: " + e);
    }
}

Never log and rethrow the same exception

Logging an exception and then rethrowing it leads to duplicate log entries. Choose either to log at a higher level or to let the caller handle logging.

try {
    new Long("xyz");
} catch (NumberFormatException e) {
    log.error(e);
    throw e;
}

Wrap exceptions without discarding the original

When converting a standard exception to a custom one, always pass the original exception as the cause. This preserves the stack trace and aids troubleshooting.

public void wrapException(String input) throws MyBusinessException {
    try {
        // do something
    } catch (NumberFormatException e) {
        throw new MyBusinessException("A message that describes the error.", e);
    }
}

Summary

In summary, handling and throwing exceptions involves many considerations aimed at improving code readability and API usability. Exceptions serve not only as an error‑control mechanism but also as a communication medium; discussing these best practices and establishing team conventions helps everyone understand and apply them consistently.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaException Handlingbest practicescoding standards
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.