SoFunction
Updated on 2025-03-04

Elegant handling of Null issues in Scala

Preface

If you still use ids!=null in scala code, you may be ridiculed by some people. It’s an era, and there is such a way to write it. Is there any less NullPointerException?
However, according to statistics:
Spark source code uses the Option keyword 821 times, but it also directly in like if (ids != null).

Spark uses a hybrid method, and in most cases Option is used, but null is used for performance (here is mainly to return prompt information for use).

A good habit is to use Option instead when there is a method that returns a value that may be null.

What is Option

In the standard class library, the Option type is represented by a sample class.Values ​​that may or may not exist
Option has two subclasses, Some and None. Some wraps a certain value, such as Some("Jack"), and None means there is no value.

Some friends saw that they were still in a fog, so they directly took a simple example to experience what this Option is:

Cook a chestnut

Here is a method to convert a string into a numeric value. The input is a string. Note that the output is not a direct output of Int, and an Option with a generic Int

def toInt(in: String): Option[Int] = {
  try {
    Some(())
  } catch {
    case e: NumberFormatException => None
  }
}

How to use this function:

toInt("s") match {
  case Some(i) => println(i)
  case None => println("The string you entered cannot be converted to a number")
}

To briefly summarize the use of this Option, it is actually to directly return the type you originally wanted to return to the generic as the Option of this type, and then return Some when writing the normal return value, and None when exception. When calling methods, match case needs to be used for processing separately.

Some people may complain when they see this: a simple null judgment, written so much, is not as simple and crude as a java to directly use i!=null to judge it simply and roughly.

But if this toInt function is written by someone else and you are a user, you will definitely encounter the following problems:

  • You don't read the API documentation and don't know that toInt may return a null, and maybe the code you wrote will throw a NullPointerException
  • You have read the API documentation and have a lot of experience using this function, knowing that it may return null, so you will definitely write the following code to handle possible null pointer exceptions
Integer i = toInt(someString);
if (i == null) {
    ("The string you entered cannot be converted to a number");
} else {
    (i);
}

This code is no worse than Scala's Option and match methods, but you do have to read the API documentation to know that it must be handled like this.

3. Of course, you can also handle null or some other exceptions by throwing a NumberFormatException.

The benefits of Option are more than that

For example, if you want to count the sum of the following list, some of these strings can be converted into Int, while others cannot

val bag = List("1", "2", "foo", "3", "bar")

To achieve this requirement, I feel that it takes a lot of code to implement it. In fact, it can be implemented in scala with just one line of code:

val sum = (toInt).sum

Why can it be implemented so simply:
Our toInt method returns Some[Int] or None, and flatMap knows how to handle these values, so it is a piece of cake to implement, and it is easy to read and understand.

This is what really awesome when using Option/Some/None mode

Simple summary of java null and scala Option

If you use a Java method written by someone else, you generally need to read the API document, or after throwing a NullPointException after using it, check the document and information and find that you need to deal with this null pointer exception. When we use scala Option, we can see that the return value is an Option[Int] (you can see the return value type directly in the IDE, and you don’t need to read the API document of the function), which means that the person who develops this function must have used the Option/Some/None combination punch, so we know that we can solve it with match case.

In my opinion, the amount of code has not decreased from the perspective of writing code, and there are two advantages:

  • More readable,
  • Avoid the disadvantages of null pointer exceptions when using functions.

Disadvantages of Option

Some people will say that in your preface, even the spark source code does not use Option to handle null values. Since you are so amazing, why don’t people use Option all of them?
Here we have to talk about one of the disadvantages of Option:
Can't tell the reason why something fails (that is, why you get a None instead of a Some) because you can't see the error exception information at all

The solution to this scala is to use Either Left and Right to handle exception information

Introduction and use of Either Left Right

Either is actually very similar to Option. The difference is that Either can return a string to describe the problem that occurs.

Comparison between Either and Option:
Either is like Option
Right Just like Some
Left is like None (but it is the reason for the problem)

Let's make some code to explain

/**
   * Here is a simple method to demonstrate how to write a method with the return value Either
   * and the usage of Left and Right in Either
   */
def divideXByY(x: Int, y: Int): Either[String, Int] = {
  if (y == 0) Left("Zero cannot be used as a divisor")
  else Right(x / y)
}

// Several different ways to use Either, Left, and Rightprintln(divideXByY(1, 0))
println(divideXByY(1, 1))
divideXByY(1, 0) match {
  case Left(s) => println("Answer: " + s)
  case Right(i) => println("Answer: " + i)
}

The above divideXByY method returns an Either[String, Int]. This generic String is the data type passed in the Left method, and Int is the data type passed in the Right method.

Through the example above, you will find that this set of things is very similar to Option/Some/None. The only difference is thatEither can send error messages back, the user can see the exception information. Let's see what the official website says:

Represents a value of one of two possible types (a disjoint union.) Instances of Either are either an instance of Left or Right.
A common use of Either is as an alternative to Option for dealing with possible missing values. In this usage,
is replaced with a Left which can contain useful information. Right takes the place of Some.
Convention dictates that Left is used for failure and Right is used for success.
To put it bluntly, it is what I wrote above. If you want to return an error message to the user, use Either. However, according to my experience, there are generally not many such scenarios. Therefore, the longest use is Option.

This is the end of this article about how to handle Null elegantly in Scala. For more related content about Scala processing Null, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!