Difference Between Using Throwable and Exception in a Try Catch

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.

What is the difference between Exception and Throwable classes?

Actually, Scala reuses exception structure from Java (so Throwable comes from Java). The class hierarchy looks like this:

         Throwable
|
------------------
| |
Error Exception
| |
errors |
-------------------
| |
runtime exceptions checked exceptions

Throwable is the superclass of all errors in Java.

Error is the superclass for errors, that are not recoverable like VirtualMachineError or ThreadDeath. Errors can be intercepted using try-catch, but usually, it's not a good practice.

Child classes of Exception are exceptions, that are intended to handled programmatically by intercepting them using try-catch.

Java also makes the difference between runtime and checked exceptions, that checked exception need to be mandatorily handled by try-catch.

Scala though handles all exceptions as runtime, so intercepting them is voluntary.

Scala has also extractor named NonFatal, which can be used to pattern match non-fatal Throwables. For example:

try {
// dangerous stuff
} catch {
//will NOT match fatal errors like VirtualMachineError, ThreadDeath, LinkageError etc.
case NonFatal(e) => log.error(e, "Something not that bad.")
}

When should Throwable be used instead of new Exception?

(from comments) The issue that brought this up is that
I need to pass an 'exception' to a
piece of code a coworker is building
if a collection does not get built.

In that case, you might want to throw a checked exception. You could throw an Exception, an appropriate existing subclass of it (except RuntimeException and its subclasses which are unchecked), or a custom subclass of Exception (e.g. "CollectionBuildException"). See the Java Tutorial on Exceptions to get up to speed with Java exceptions.

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.

Why does vavr's Try container catches Throwable but not Exception?

The reason that Throwable was used instead of Exception, is because we want our Try objects to also catch Errors. This his how the inheritance model of Exceptions and Errors looks like:

Sample Image

If we only catch Exceptions, an IOError would crash our code and prevent us from using the strength of a Try chain:

Try.of(() -> throw new IOError(null))
.onFailure(() -> /* Do something to fix the IOError */);

When catching Throwable, this IOError will be caught, and we will be able to execute the onFailure method. If we only catch Exception, the execution would have stopped on line one, and the onFailure would never be executed.

PHP: What is the difference between an exception and a catchable fatal error?

Fatal errors can not necessarily be caught (they do not throw usual
exceptions)

Prior to version 7, this was the case. Fatal errors used to stop the script dead in its tracks. However, as of version 7, they're now presented as catchable exceptions. This allows you to gracefully recover from pretty significant issues.

However how is a Catchable Fatal Error different from a normal
Exception?

They both implement Throwable, but with different anchor classes:

Throwable
Error
ParseError
...
Exception
RuntimeException
...

And is it handled the same?

Yep, you can catch them, just like Exceptions.

Is a catchable fatal error a
specific type of exception or not?

Depends on your semantics. A catchable fatal error is an exception but it's not an Exception, if you get my meaning. You can differentiate like this;

// "traditional" exceptions
try {
throw new Foo();
} catch (Exception $e) {
}

// v7 catchable fatal errors
try {
$not_an_object->not_a_method();
} catch (Error $e) {
}

// both
try {
} catch (Throwable $e) {
}

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.

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