Generally we rethrow exceptions. In Java we do that extra typically than in different languages, as a result of it has checked exceptions. Generally we should catch and rethrow a number of exceptions that originated from completely different locations in a technique. Java 7 launched grouping of various kinds of exceptions in a single catch
block. However even with out the grouping, it’s attainable to simply catch IOException
and even Exception
and supply a single catch
block for all sorts and all originators (strategies that throw). Just lately I spotted that it is a unhealthy follow. Right here is why.
Think about this Java technique (I’m utilizing Apache Commons IO):
byte[] learn(String uri) {
attempt {
return IOUtils.toByteArray(
new URL(uri).openStream()
);
} catch (IOException ex) {
throw new IllegalArgumentException(ex);
}
}
It’s not good. Let’s rewrite it to supply extra error context, as was suggested earlier:
byte[] learn(String uri) {
attempt {
return IOUtils.toByteArray(
new URL(uri).openStream()
);
} catch (IOException ex) {
throw new IllegalArgumentException(
String.format(
"Didn't learn from '%s'",
uri
),
ex
);
}
}
Right here, the exception could also be thrown in three locations:
Irrespective of who throws, we catch it in the identical catch
block and rethrow with the identical message. I consider that that is unhealthy as a result of the context of the error offered by rethrowing is much less targeted on the difficulty that occurred.
I might counsel this refactoring (I don’t shut the enter stream, which is fallacious, however that’s a subject for a separate dialogue):
byte[] learn(String uri) {
URL url;
attempt {
url = new URL(uri);
} catch (MalformedURLException ex) {
throw new IllegalArgumentException(
String.format(
"Didn't parse the URI '%s'",
uri
),
ex
);
}
InputStream stream;
attempt {
stream = url.openStream();
} catch (IOException ex) {
throw new IllegalArgumentException(
String.format(
"Didn't open the stream for '%s'",
uri
),
ex
);
}
attempt {
return IOUtils.toByteArray(stream);
} catch (IOException ex) {
throw new IllegalArgumentException(
String.format(
"Didn't learn the stream for '%s'",
uri
),
ex
);
}
}
This code is for much longer, however on the similar time extra handy to debug, check, and use in manufacturing mode. The catch
block is ready to clarify the state of affairs higher and supply higher context within the rethrown exception, as a result of it offers solely with a single case.
Thus, the rule I’m suggesting: if an exception is caught, every originator will need to have its personal catch
block.
Clearly, I consider that grouping exception types in a single catch
block is unhealthy follow.