Scala Uses Option, Some, and None to Avoid Using Null
Category Programming Techniques
Avoiding the use of null
Most languages have a special keyword or object to represent that an object reference is "nothing". In Java, it's null. In Java, null is a keyword, not an object, so calling any method on it is illegal. But this is a puzzling choice for language designers. Why return a keyword when programmers expect to return an object?
Scala's Option Type
To make the goal of everything being an object more consistent and to follow the habits of functional programming, Scala encourages you to use the Option type when variables and function return values might not reference any value. When there is no value, use None, which is a subclass of Option. If there is a value to reference, use Some to contain this value. Some is also a subclass of Option. None is declared as an object, not a class, because we only need one instance of it. In this way, it is somewhat similar to the null keyword, but it is a real, method-equipped object.
Application Example
Values of the Option type are usually used as the return type for operations on Scala collection types (List, Map, etc.). For example, the get method of Map:
scala> val capitals = Map("France"->"Paris", "Japan"->"Tokyo", "China"->"Beijing")
capitals: scala.collection.immutable.Map[String,String] = Map(France -> Paris, Japan -> Tokyo, China -> Beijing)
scala> capitals get "France"
res0: Option[String] = Some(Paris)
scala> capitals get "North Pole"
res1: Option[String] = None
Option has two subcategories, Some and None. When the program returns Some, it means the function has successfully given you a String, and you can get that String through the get() function. If the program returns None, it means there is no string to give you.
scala> capitals get "North Pole" get
warning: there was one feature warning; re-run with -feature for details
java.util.NoSuchElementException: None.get
at scala.None$.get(Option.scala:347)
at scala.None$.get(Option.scala:345)
... 33 elided
scala> capitals get "France" get
warning: there was one feature warning; re-run with -feature for details
res3: String = Paris
scala> (capitals get "North Pole") getOrElse "Oops"
res7: String = Oops
scala> capitals get "France" getOrElse "Oops"
res8: String = Paris
Separate the optional value by pattern matching. If the matched value is Some, extract the value inside Some and assign it to the variable x:
def showCapital(x: Option[String]) = x match {
case Some(s) => s
case None => "?"
}
Tip
Scala programs use Option very frequently. In Java, null is used to represent null values, and null keyword checks must be added in many places in the code to avoid NullPointerException. Therefore, Java programs need to be concerned about which variables may be null, and the possibility of these variables being null is very low, but once they appear, it is difficult to find out why NullPointerException occurs. Scala's Option type can avoid this situation, so Scala applications are recommended to use the Option type to represent some optional values. With the use of Option type, readers can see at a glance that the value of this type may be None.
In fact, thanks to Scala's static typing, you cannot mistakenly try to call a method on a value that may be null. Although this is an easy mistake to make in Java, it will not pass Scala's compilation, because Java does not check whether a variable is null as a programming error that becomes a type error in Scala (Option[String] cannot be used as String). Therefore, the use of Option strongly encourages more flexible programming habits.
Detailed Explanation of Option[T]
In Scala, Option[T] is actually a container, just like an array or List. You can think of it as a List that may have zero to one element.
When there is something in your Option, the length of this List is 1 (i.e., Some), and when there is nothing in your Option, its length is 0 (i.e., None).
for Loop
If we treat Option as a general List and use a for loop to visit the Option, if Option is None, then the code in the for loop will naturally not be executed, so we achieve the goal of "not having to check whether Option is None."
``` scala> val map1 = Map("key1" ->