In this StackOverflow question I asked about the behavior of the @throws
annotation in Scala. Now that I understand how it works I want to ask about best practices with using it. Here’s a repost of my code from that question:
abstract class SFoo {
def bar(): Unit
}
class SFoobar extends SFoo {
@throws[Exception]
override def bar(): Unit = {
throw new Exception("hi there")
}
}
The problem here is that if I declare a variable as a SFoo
in Java, but instantiate it as a SFoobar
, the Java compiler is unable to detect the checked exception and a runtime exception will occur. So my inclination would be to declare @throws
in the parent class, SFoo
.
But say I have another concrete implementation of SFoo
:
class SBarfoo extends SFoo {
override def bar(): Unit = {
println("no exception here!")
}
}
In this case, is it appropriate to declare @throws
in the parent class if one of its implementations does not throw an exception? What is the best practice here? (Sorry for the subjective question.)
You don’t have to throw the exception every single time in order for the @throws
contract to be fulfilled. In fact, the vast majority of the time, you won’t. There’s nothing wrong with having an implementation that never throws an exception, if it truly belongs as a subclass. I can think of lots of applications where that would make sense. For example, one implementation might use a disk cache, where another one might use a memory cache.
That being said, Scala purposely omitted checked exceptions for a good reason: they violate the open/closed principle because you can’t throw a new exception in a subclass without propagating it around to all the existing classes in the hierarchy, as well as methods calling those methods. Checked exceptions were omitted from C# and other recent languages in large part because of how problematic checked exceptions proved to be in real life Java applications. Scala only has checked exceptions for compatibility with Java code. If you won’t be calling Scala code from Java code, you shouldn’t use them.
4