We’re very used to Java’s notion of checked exceptions. If we want to force the developer to consider exceptional behaviour then we typically throw a checked exception. The problem is that despite our best intentions, we can’t force the developer to actually deal with the exception sensibly. Java tries to help by forcing a compilation error onto the developer so they at least forced to choose a course of action. The trouble is though it’s all too tempting to swallow exceptions or just rethrow. We tend to either bury our heads in the sand or litter our code with addition noise.
Scala has taken a different approach. Scala has done away with checked exceptions; all exceptions are effectively RuntimeException
s and so its left to the developer to decide when to handle them. This obviously leads to less noise but puts more responsibility on the developer. Scala makes it easy to avoid the issue but without a clear system wide policy for exception handling, we can still get into trouble.
In a previous post, I’ve described a general approach to understanding when and how to deal with exceptions in Scala or Java. In this post, we’ll take a quick look at Scala’s syntax around exceptions and how pattern matching is employed.
Exceptions
Scala essentially treats all exception types as RuntimeException
. This means it doesn’t force you to handle exceptions. Instead, it combines pattern matching with a single catch
block to handle exceptions. For example
|
Any cleanup can be achieved using the finally
block as expected. This works exactly the same way as in Java but perhaps a more idiomatic alternative is to use the loan pattern. You can see an example of the pattern in Java form in the ExecuteUsingLock
class in tempus-fugit.
Throwing exceptions is done in the same way as Java, as in the example below.
|
However, anyone calling this method won’t be forced by the compiler to catch the exception. If you intend to call your Scala code from Java however, you can force checked exceptions using the throws
annotation but this still won’t affect Scala clients.
|
Interestingly, Scala treats throw
as an expression with a return type of Nothing
. You can use it in place of any other expression even though the result wont actually evaluate to anything.
Pattern Matching
Pattern matching is a bit like a switch statement but unlike Java’s switch statement, pattern matching in Scala can be used to match any kind of constant as well as other things (like case objects). It’s not restricted to just primitives and enums as with Java (although Java 1.7 brought String
support to switch).
Pattern matching is applied to the exception type when using catch
above but it’s also used in its vanilla form. For example, as described in Programming in Scala, we can work out what to have with dinner in the example below.
|
Notice that there is no need for a break
statement and that each match expression results in a value. So we can take advantage of resulting value and rewrite the above to the following.
|
Conclusion
The whole thing is generally neater than the Java equivalent but as I keep banging on about, we still need to carefully consider where to apply the catch
when handling exceptions. When using Scala, it’s even more important to understand where potential exceptions will bubble up and how to handle them as a system wide concern.