Search code examples
javaexceptionsonarlintchecked-exceptionssonarlint-eclipse

What's wrong with throwing multiple checked exceptions in Java?


Consider the Java code snippet below:

public <T> T create(Class<T> clazz) throws InstantiationException, IllegalAccessException {
    return clazz.newInstance();
}

This in Eclipse (Neon.2, JDK 8) with SonarLint performing static code analysis. It is providing a recommendation to refactor this:

Refactor this method to throw at most one checked exception instead of: java.lang.InstantiationException, java.lang.IllegalAccessException

What best practice is the basis for this recommendation? I understand there's some controversy about checked exceptions in general, but why would it be better in this instance to catch one here and pass the other up the stack vs. passing them both up the stack for something else to handle them?


Solution

  • What best practice is the basis for this recommendation?

    "Best practice" implies that there is a single objectively correct answer to the question. There isn't one.

    Why would it be better in this instance to catch one here and pass the other up the stack vs. passing them both up the stack for something else to handle them?

    In this case, you wouldn't do that. Both IllegalAccessException and InstantiationException are subtypes of ReflectiveOperationException. If you wanted to reduce the signature to a single checked exception (as suggested by the checker) you would use that exception.

    In general, the argument for unifying (by either picking an existing superclass or by redesigning the exception hierarchy) is that the caller needs to handle fewer exceptions.

    But the counter-argument to that is that when you unify the throws list, you are hiding information from the programmer / compiler. For example if the API was changed to this:

    public <T> T create(Class<T> clazz) throws ReflectiveOperationException {
        ...
    }
    

    programmer using that API no longer knows which kinds of reflective operation exception can be thrown. And when you "unify" by catching, wrapping and throwing as a new exception, it is even worse.

    Note that I'm not saying that either approach is wrong. What I'm saying is that the context should determine which approach you take. In other words, appealing to "best practice" is missing the point.