This rule raises an issue when a generic exception (such as Error
, RuntimeException
, Throwable
, or
Exception
) is thrown.
Why is this an issue?
Throwing generic exceptions such as Error
, RuntimeException
, Throwable
, and Exception
will have
a negative impact on any code trying to catch these exceptions.
From a consumer perspective, it is generally a best practice to only catch exceptions you intend to handle. Other exceptions should ideally be let
to propagate up the stack trace so that they can be dealt with appropriately. When a generic exception is thrown, it forces consumers to catch
exceptions they do not intend to handle, which they then have to re-throw.
Besides, when working with a generic type of exception, the only way to distinguish between multiple exceptions is to check their message, which is
error-prone and difficult to maintain. Legitimate exceptions may be unintentionally silenced and errors may be hidden.
For instance, when a Throwable
is caught and not re-thrown, it may mask errors such as OutOfMemoryError
and prevent the
program from terminating gracefully.
When throwing an exception, it is therefore recommended to throw the most specific exception possible so that it can be handled intentionally by
consumers.
Exceptions
Generic exceptions in the signatures of overriding methods are ignored, because an overriding method has to follow the signature of the throw
declaration in the superclass. The issue will be raised on superclass declaration of the method (or won’t be raised at all if superclass is not part
of the analysis).
@Override
public void myMethod() throws Exception {...}
Generic exceptions are also ignored in the signatures of methods that make calls to methods that throw generic exceptions.
public void myOtherMethod() throws Exception {
doTheThing(); // this method throws Exception
}
How to fix it
To fix this issue, make sure to throw specific exceptions that are relevant to the context in which they arise. It is recommended to either:
- Raise a specific exception from the Java standard library when one matches. For example an
IllegalArgumentException
should be
thrown when a method receives an invalid argument.
- Create a custom exception class deriving from
Exception
or one of its subclasses.
Code examples
Noncompliant code example
void checkValue(int value) throws Throwable { // Noncompliant: signature is too broad
if (value == 42) {
throw new RuntimeException("Value is 42"); // Noncompliant: This will be difficult for consumers to handle
}
}
Compliant solution
void checkValue(int value) {
if (value == 42) {
throw new IllegalArgumentException("Value is 42"); // Compliant
}
}
Resources
Standards
Related rules
- S1181 - Generic exceptions should not be caught