I think it's very rare that
you should ever write a catch block that
specifically catches a NullPointerException, ArrayIndexOutOfBoundsException, or other common runtime exceptions where it's easier to write a simple check
before calling the method, rather than trying to pick of the pieces later. The only exception I can think of to this guideline is: it's possible there's a third-party library, outside your direct control, which usually does something useful (which you can't easily do yourself) but which occasionally throws a specific exception. In such cases you may have analyzed the behavior, and determined that the best you can do is catch the specific exception, when it happens, and then execute some workaround. Meanwhile, you file a bug report, and hope the author(s) of the code will fix the problem in a later release. This is rare, but sometimes, it happens. But for any code that you control yourself, you should never need to do this.
(Well, another exception is
test code, where you intentionally create a situation which violates the contract of a method, and then verify that the appropriate exception is thrown. Nowadays most of us handle that with
JUnit's @Test(expected) annotation. But sometimes you may require more precise handling than @Test offers. Anyway, test code often violates the rules of what you should do in production-level code.)
But more generally, sometimes it's entirely appropriate to write a more general catch block, such as a catch (RuntimeException e), catch (Exception e), or occasionally even catch (Throwable t). Yes, really. The thing is, while it's nice to assert that all so-called "programmer errors" (a simplistic view of runtime exceptions) shlud have been caught in testing, before release... well, sometimes it just doesn't happen. Often, really. And it's not unreasonable to install a few extra safeguards at select spots in the program. Thanks that say, look, even if we screw up the current file/order/request somehow, don't exit the program entirely. Log the error, whatever it is, and then try the next file/order/request/whatever. Some mistakes may happen, but that doesn't mean you should abandon everything. Some systems need to be a little more flexible than that. In such cases, it's
entirely reasonable to catch all RuntimeExceptions, all Exceptions, or maybe even all Throwables. Yes, really.
And some people will probably tell you you shouldn't catch an Error. As general advice, especially for beginners, that's very good advice. But if anyone tells you that you should
never catch an Error... ignore them. They really don't know what they're talking about. And reasoning with them probably isn't worth the hassle. Better to just wait for them to evolve or die.