Scala:符合惯用风格的Try匹配及避免捕获Throwable的方法
Try Pattern Matching Without Catching Non-Exception Throwables Great question! Scala's default Try does catch all Throwable instances—including fatal ones like AssertionError, OutOfMemoryError, or StackOverflowError—which isn't always what we want, since these are usually meant to signal unrecoverable issues. Here are a couple of idiomatic Scala approaches to handle this properly:
1. Add a Guard Clause in Pattern Matching
The simplest approach is to refine your Failure case to only match Exception types, and rethrow any non-Exception Throwables. This keeps your matching logic explicit and aligned with Scala's pattern matching style:
Try(throw new AssertionError("assertion error")) match { case Success(_) => println("success") case Failure(exc: Exception) => println(s"caught: $exc") case Failure(fatalThrowable) => // Re-throw fatal errors instead of handling them throw fatalThrowable }
In this example, AssertionError (which is a Throwable but not an Exception) will trigger the third case and be rethrown, instead of being caught and logged.
2. Create a Reusable "Safe Try" Wrapper
If you need this behavior across multiple parts of your codebase, you can encapsulate the logic into a custom utility object. This avoids repeating the guard clause everywhere and keeps your code DRY:
object SafeTry { def apply[T](block: => T): Try[T] = { try { Success(block) } catch { case exc: Exception => Failure(exc) // Let fatal non-Exception Throwables propagate as intended case fatal: Throwable => throw fatal } } }
Now you can use SafeTry just like the standard Try, but it will only catch Exceptions:
SafeTry(throw new AssertionError("assertion error")) match { case Success(_) => println("success") case Failure(exc) => println(s"caught: $exc") }
Here, the AssertionError won't be caught by the Failure case—it will bubble up as a fatal error, which is the correct behavior for such issues.
Why This Matters
Fatal Throwables like AssertionError or VirtualMachineError are designed to indicate severe, unrecoverable problems with the JVM or your program's invariants. Catching them can hide critical issues and make debugging harder, so rethrowing them aligns with best practices.
内容的提问来源于stack exchange,提问作者sumitsu

