In this article, it's said that:
If you want to catch “everything” that would normally happen, then use NonFatal:
import scala.util.control.NonFatal try { operation() } catch { case NonFatal(e) => errorHandler(e) }
But I usually use Exception
:
try { operation() } catch { case e: Exception => errorHandler(e) }
I would like to know what is the difference between NonFatal
and Exception
in Scala? Does Exception
in Scala include fatal exception?
AFAIK in java, Exception
is for non-fatal error and Error
is for fatal error. Is scala different with java in term of Exception
?
Which way is the correct one to catch non-fatal exception?
A non-fatal error is a failure in your application that didn't result in a crash for the user. In other words: the loss is recoverable, and the application can continue.
An exception is an event that changes the normal flow of a program. Exception handling is the mechanism to respond to the occurrence of an exception. Exceptions can be checked or unchecked. Scala only allows unchecked exceptions, though.
Non-fatal errors are diagnostic indications of user errors, usually in application development. For example, a non-fatal error code is returned when a user attempts to destroy a non-existent table. These errors are not severe and do not halt the user program or Vector.
Edit: updated for the latest Scala version (2.11+ has a different definition of NonFatal.apply
).
NonFatal
is just a convenient extractor which is defined in scala.util.control
:
object NonFatal { /** * Returns true if the provided `Throwable` is to be considered non-fatal, or false if it is to be considered fatal */ def apply(t: Throwable): Boolean = t match { // VirtualMachineError includes OutOfMemoryError and other fatal errors case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false case _ => true } /** * Returns Some(t) if NonFatal(t) == true, otherwise None */ def unapply(t: Throwable): Option[Throwable] = if (apply(t)) Some(t) else None }
There is no special "fatal" kind of exceptions on JVM - Error
s are not always "fatal", they're just a special kind of internal exceptions. "Fatal" exceptions are just a list of exceptions used in NonFatal
definition. In this terminology all Exception
s except InterruptedException
are considered non-fatal. It makes sense to consider InterruptedException
fatal because it means that the thread is interrupted, so if you want to handle it you should do it explicitly.
NonFatal
extractor also handles ControlThrowable
s correctly. These are exceptions which are thrown by special control transfer functions like break
inside breakable
.
Exceptions don't get mentioned very much in Scala, but they're still what is done multiple times when dealing with unexpected failure.
When we look for When to catch java.lang.Error? multiple answers, and opinions will be present, but let's focus on the common part.
A reasonable application should not try to catch
NonFatal
is an Extractor of non-fatal Throwables. Will not match fatal errors like VirtualMachineError
(for example, OutOfMemoryError
and StackOverflowError
, subclasses of VirtualMachineError
), ThreadDeath
, LinkageError
, InterruptedException
, ControlThrowable
, that are part of the failures a reasonable application should'nt try to catch.
With this in mind, we could write code that catches all harmless Throwables can be caught by:
try { // dangerous code } catch { case NonFatal(e) => log.error(e, "Something not that bad.") }
If we look at the apply method we can see it very clearly.
object NonFatal { /** * Returns true if the provided `Throwable` is to be considered non-fatal, or false if it is to be considered fatal */ def apply(t: Throwable): Boolean = t match { // VirtualMachineError includes OutOfMemoryError and other fatal errors case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false case _ => true } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With