In Java (and other languages), using null
is a common way of indicating that there is no value attached to a reference variable. In Scala, using Option
is preferred over using null
. Option
wraps values that might be null
.
None
is a subclass of Option
wrapping a null reference. Some
is a subclass of Option
wrapping a non-null reference.
Wrapping a reference is easy:
val nothing = Option(null) // None
val something = Option("Aren't options cool?") // Some("Aren't options cool?")
This is typical code when calling a Java library that might return a null reference:
val resource = Option(JavaLib.getResource())
// if null, then resource = None
// else resource = Some(resource)
If getResource()
returns a null
value, resource
will be a None
object. Otherwise it will be a Some(resource)
object. The preferred way to handle an Option
is using higher order functions available within the Option
type. For example if you want to check if your value is not None
(similar to checking if value == null
), you would use the isDefined
function:
val resource: Option[Resource] = Option(JavaLib.getResource())
if (resource.isDefined) { // resource is `Some(_)` type
val r: Resource = resource.get
r.connect()
}
Similarly, to check for a null
reference you can do this:
val resource: Option[Resource] = Option(JavaLib.getResource())
if (resource.isEmpty) { // resource is `None` type.
System.out.println("Resource is empty! Cannot connect.")
}
It is preferred that you treat conditional execution on the wrapped value of an Option
(without using the 'exceptional' Option.get
method) by treating the Option
as a monad and using foreach
:
val resource: Option[Resource] = Option(JavaLib.getResource())
resource foreach (r => r.connect())
// if r is defined, then r.connect() is run
// if r is empty, then it does nothing
If a Resource
instance is required (versus an Option[Resource]
instance), you can still use Option
to protect against null values. Here the getOrElse
method provides a default value:
lazy val defaultResource = new Resource()
val resource: Resource = Option(JavaLib.getResource()).getOrElse(defaultResource)
Java code won't readily handle Scala's Option
, so when passing values to Java code it is good form to unwrap an Option
, passing null
or a sensible default where appropriate:
val resource: Option[Resource] = ???
JavaLib.sendResource(resource.orNull)
JavaLib.sendResource(resource.getOrElse(defaultResource)) //