How to declare that a Scala method can throw an exception

This is an excerpt from the 1st Edition of the Scala Cookbook (partially modified for the internet). This is Recipe 5.8, “How to declare that a Scala method can throw an exception.”

Problem

You want to declare that a Scala method can throw an exception, either to alert callers to this fact or because your method will be called from Java code.

Solution

Use the @throws annotation to declare the exception(s) that can be thrown. To declare that one exception can be thrown, place the annotation just before the method signature:

@throws(classOf[Exception])
override def play {
    // exception throwing code here ...
}

To indicate that a Scala method can throw multiple exceptions, list them all before the method signature:

@throws(classOf[IOException])
@throws(classOf[LineUnavailableException])
@throws(classOf[UnsupportedAudioFileException])
def playSoundFileWithJavaAudio {
    // exception throwing code here ...
}

Discussion

The two examples shown are from an open source project I created that lets developers play WAV, AIFF, MP3, and other types of sound files. I declared that these two methods can throw exceptions for two reasons. First, whether the consumers are using Scala or Java, if they’re writing robust code, they’ll want to know that something failed. Second, if they’re using Java, the @throws annotation is the Scala way of providing the throws method signature to Java consumers.

The example I showed is equivalent to declaring that a Java method throws an exception with this syntax:

public void play() throws FooException {
    // code here ...
}

It’s important to note that Scala’s philosophy regarding checked exceptions is different than Java’s. Scala doesn’t require that methods declare that exceptions can be thrown, and it also doesn’t require calling methods to catch them. This is easily demonstrated in the REPL:

// 1) it's not necessary to state that a method throws an exception
scala> def boom {
     |     throw new Exception
     | }
boom: Unit

// 2) it's not necessary to wrap 'boom' in a try/catch block, but ...
scala> boom
java.lang.Exception
    at .boom(<console>:8)
    // much more exception output here ...

Although Scala doesn’t require that exceptions are checked, if you fail to test for them, they’ll blow up your code just like they do in Java. In the following example, the second println statement is never reached because the boom method throws its exception:

object BoomTest extends App {
    def boom { throw new Exception }
    println("Before boom")
    boom
    // this line is never reached
    println("After boom")
}

Java Exception Types

As a quick review, Java has (a) checked exceptions, (b) descendants of Error, and (c) descendants of RuntimeException. Like checked exceptions, Error and RuntimeException have many subclasses, such as RuntimeException’s famous offspring, NullPointerException.

According to the Java documentation for the Exception class, “The class Exception and any subclasses that are not also subclasses of RuntimeException are checked exceptions. Checked exceptions need to be declared in a method or constructor’s throws clause if they can be thrown by the execution of the method or constructor and propagate outside the method or constructor boundary.”

The following links provide more information on Java exceptions and exception handling:

See Also