Why Catch Exceptions in Java, When You Can Catch Throwables

Why catch Exceptions in Java, when you can catch Throwables?

It all depends a bit on what you're going to do with an Error once you've caught it. In general, catching Errors probably shouldn't be seen as part of your "normal" exception flow. If you do catch one, you shouldn't be thinking about "carrying on as though nothing has happened", because the JVM (and various libraries) will use Errors as a way of signalling that "something really serious has happened and we need to shut down as soon as possible". In general, it's best to listen to them when they're telling you the end is nigh.

Another issue is that the recoverability or not from an Error may depend on the particular virtual machine, which is something you may or not have control over.

That said, there are a few corner cases where it is safe and/or desirable to catch Errors, or at least certain subclasses:

  • There are cases where you really do want to stop the normal course of flow: e.g. if you're in a Servlet, you might not want the Servlet runner's default exception handler to announce to the world that you've had an OutOfMemoryError, whether or not you can recover from it.
  • Occasionally, an Error will be thrown in cases where the JVM can cleanly recover from the cause of the error. For example, if an OutOfMemoryError occurs while attempting to allocate an array, in Hotspot at least, it seems you can safely recover from this. (There are of course other cases where an OutOfMemoryError could be thrown where it isn't safe to try and plough on.)

So the bottom line is: if you do catch Throwable/Error rather than Exception, it should be a well-defined case where you know you're "doing something special".

Edit: Possibly this is obvious, but I forgot to say that in practice, the JVM might not actually invoke your catch clause on an Error. I've definitely seen Hotspot glibly gloss over attempts to catch certain OutOfMemoryErrors and NoClassDefFoundError.

Difference between using Throwable and Exception in a try catch

By catching Throwable it includes things that subclass Error. You should generally not do that, except perhaps at the very highest "catch all" level of a thread where you want to log or otherwise handle absolutely everything that can go wrong. It would be more typical in a framework type application (for example an application server or a testing framework) where it can be running unknown code and should not be affected by anything that goes wrong with that code, as much as possible.

Is it a bad practice to catch Throwable?

You need to be as specific as possible. Otherwise unforeseen bugs might creep away this way.

Besides, Throwable covers Error as well and that's usually no point of return. You don't want to catch/handle that, you want your program to die immediately so that you can fix it properly.

Catching throwable and handling specific exceptions

There are various reasons why you should not catch a Throwable. First of all is, that Throwable includes Errors - and there's normally not much an application can do if one of these appears. Also Throwable reduces your chances of finding out, WHAT has happened. All you get is "something bad has happened" - which might be a catastrophe or just a nuisance.

The other aproach is better but of course I still would not catch Throwable, but try to catch more specific Exceptions, if possible at all. Otherwise you are catching everything and then try to sort out which kind of bad thing happened. Your example could be written as...

try {
...
} catch (SQLEXception ex){
response = ... ;
} catch (IllegalArgumentException ex){
response = ...;
}

...which would reduce the amount of if ( ... instanceof ... ) blocks (which are only needed because the author first decided to catch everything in one big bucket). It something actually throws Throwable, then you don't have much choice, of course.

Handle Multiple Throwable In A Catch Block In JAVA

What you are describing is collapsing multiple catch blocks together. This has been possible at least since Java 8.

Here's an example of catching three different exception types and handling them all in the same way:

try {
// do things here
} catch (IllegalAccessException | IllegalStateException | ConnectException e) {
// handle exceptions here
}

You can have multiple collapsed catch blocks, too. Here's an example:

try {
// do things here
} catch (IllegalAccessException | IllegalStateException | ConnectException e) {
// handle exceptions here
} catch (IllegalArgumentException | IllegalMonitorStateException e) {
// handle these exceptions differently from the first set
}

Should I catch Exception, Throwable or other in EventDispatcher/Observable

I'd recommend catching Throwable as I find your argument conclusive that “an event publisher might be observed by anyone, meaning that the event listener might throw exceptions that the event publisher cannot possibly know”.

The alternatives are not catching anything, which would be a nightmare, or your suggestion of a thread pool, which I believe is unnecessary when you catch Throwable.

Why try/catch around throwable?

My guess is that your trying to throw an exception sub class that isn't declared by the method as an exception type it can throw.

The following example works

package test.example;

public class ExceptionTest {

public static void main(String[] args) throws Exception{
try {
int value = 1/0;
} catch (Exception e) {
System.out.println("woops the world is going to end");
throw e;
}

}

}

However this example will give an error.

package test.example;

public class ExceptionTest {

public static void main(String[] args) throws RuntimeException{
try {
int value = 1/0;
} catch (Exception e) {
System.out.println("woops the world is going to end");
throw e;
}

}

}

Note in the second example I'm simply catching Exception not RuntimeException, it won't compile as I throw Exception which is an undeclared throws, even though I do declare RuntimeException.

Yes the exception is a RuntimeException but the compiler doesn't know that.

Just thought of a third working example to show you. This one also works because your throwing the same type as you declare. (note the only change is the catch block)

package test.example;

public class ExceptionTest {

public static void main(String[] args) throws RuntimeException{
try {
int value = 1/0;
} catch (RuntimeException e) {
System.out.println("woops the world is going to end");
throw e;
}

}

}

You need to understand the differences between all three of these answers



Related Topics



Leave a reply



Submit