Ok, to start with, the recommendation is to use None instead of null. Ideally if in Scala code, we end up getting a NPE then that is sin! Well at least at Knoldus :)
null in Java is used as a placeholder for denoting no value or a non-fatal error situation. It is widely accepted as a Billion dollar mistake of Java. The way to work around it is to have a NullObjectPattern which is present as a pattern in variety of languages and which people seldom use.
Scala is smart. It has an option which is a container. Now the container can either have something or it can be empty. Most of the times developers working in Scala use it in either of the two situations
First, when they are working with a Java API which possibly returns null. Since you would not want to work with null in Scala then you would wrap the Java API call in an Option. Something like this
def someCrappyJavaService = null //> someCrappyJavaService: => Null val result = Option(someCrappyJavaService) //> result : Option[Null] = None if (result==None) println("bla") //> bla
If you would notice, most of the developers coming from the Java world would be writing code like this.
However, Option provides us with lot of cool ways to implement our logic. For starters, instead of checking == you could instead do
def someCrappyJavaService = null //> someCrappyJavaService: => Null val result = Option(someCrappyJavaService)//> result : Option[Null] = None if (!result.isDefined) println("bla") //> bla
Ok, i see you throwing a stone at me. What is the big deal here? You could also do a getOrElse
def someCrappyJavaService = null val result = Option(someCrappyJavaService).getOrElse("bla") println(result)
Still, what is the big deal? Well, we have just started!
One of the cool feature of option is that it can be treated like a collection. What? Yes, you can call methods like map, flatMap, foreach and use it in for comprehensions. Let us see how that makes things easier for us.
We want to execute a portion of the logic only if we have got a value in the Option container. There is “a” way and then a better way to do it. See the code below
val result = None //Some("Hello") def someProcessingLogic(x: String) = println(s"I would execute when there is some value like $x") //Standard Way if (result != None) someProcessingLogic(result.get) // Better Way! for (res <- result) someProcessingLogic(res)
Now the for comprehension would evaluate only if res is not an empty box i.e. it has some value. But, what if there are multiple options that we want to compose together. For example the following code block