Using Scala 3 Explicit Nulls

Learn about Scala 3's explicit nulls feature, which improves type safety by making nullability part of the type system. Discover how Null is no longer connected to AnyRef, reducing null pointer exceptions and enhancing code robustness. Explore the benefits of Scala 3's updated type hierarchy.

Using Scala 3 Explicit Nulls
Say Good Bye to null checks in code.

Introduction

Scala 3 introduces new features to improve the language's type safety and developer productivity.

One of the standout features is explicit null support. This feature significantly enhances the handling of null values, making our code safer and more robust.

This article will explore explicit nulls, how to use them, and why they are beneficial.


What Are Explicit Nulls?

Scala was born as a JVM language, and interoperability with Java has been an essential goal. This is why Scala has allowed null values. It does this by making every type inheriting from AnyRef nullable:

Diagram of Scala's type hierarchy, showing relationships between Any, AnyVal, AnyRef, Matchable, Null, Nothing, and various value and reference classes.
The Scala Object Hierarchy (Source: https://docs.scala-lang.org/scala3/reference/experimental/explicit-nulls.html)

But Scala also pursues type safety, and nulls are one of the most notable sources of bugs and unexpected behavior.

🧠
I call it my billion-dollar mistake. It was the invention of the null reference in 1965... At that time, I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. - Tony Hoare

Scala 3 includes an optional feature that changes the hierarchy not automatically to make AnyRef types nullable:

Diagram of Scala's type hierarchy, illustrating relationships between Any, Matchable, AnyVal, AnyRef, Null, Nothing, and various value and reference classes. Note that Null is no longer connected to AnyRef.
The Scala Object Hierarchy with Explicit Nulls (Source: https://docs.scala-lang.org/scala3/reference/experimental/explicit-nulls.html)

With explicit nulls activated, Scala 3 makes Null a type that doesn't have a relation to AnyRef. This means that trying to assign null to a variable of any type inheriting from AnyRef will cause a compilation error.

This increases the type safety of our Scala code but could make it harder to interact with Java code since the compiler does not get enough information to ensure references received from it are not null. This is why it is an Opt-In and not a default feature.

There might still be legitimate cases to allow Null as a value from some variables; in those cases, we will need to use Union Types (T | Null) to explicitly mark a variable or type as Null-allowing.


Enabling Explicit Nulls

We need to enable the feature in your Scala 3 project to use explicit nulls. We can do it by adding the following setting to our build.sbt:

SBT

scalacOptions += "-Yexplicit-nulls"
        

Once enabled, the compiler will enforce nullability rules, helping you identify and handle nulls more effectively.

Working with Explicit Nulls

Once we activate this feature, null checks become unnecessary. We won't need to wrap our reference around Options because the compiler will ensure the variable never contains a null value.

For those occasions when we need to allow nulls, like when interacting with Java code, we'll have to use Union Types and then treat the variable as if it can hold a null:

Scala 3

val nullableString: String | Null = getNullableString()

val safeString: Option[String] = Option(nullableString)

safeString match {
  case Some(value) => println(s"String value: $value")
  case None => println("Value is null")
}
        

Using explicit nulls provides several benefits:

  • Enhanced Type Safety: By making nullability explicit, the compiler can catch potential null pointer exceptions, reducing runtime errors.
  • Improved Code Clarity: Explicit nulls make the intent of your code more transparent. It is immediately apparent which values can be null.
  • Better Interoperability: Explicit nulls improve interoperability with Java and other languages that use nulls extensively.

Conclusion

Scala 3's explicit nulls feature is a powerful addition to the language. It offers enhanced type safety and clarity, and making nullability explicit forces us to write more robust and maintainable code.

If you haven't already, consider enabling explicit nulls in your Scala 3 projects to take advantage of these benefits.


Addendum: A Special Note for Our Readers

I decided to delay the introduction of subscriptions. You can read the full story here.

In the meantime, I'll be accepting donations. I would appreciate it if you consider a donation, provided you can afford it:

Every donation helps me offset the site's running costs and an unexpected tax bill. Any amount is greatly appreciated.

Also, if you are looking for a fancy way to receive 2025, I am renting my timeshare in Phuket to cover part of the unexpected costs.

Anantara Vacation Club Phuket Mai Khao $2000.00/night
Phuket, Thailand / Posting R1185060

Or share our articles and links page in your social media posts.

Finally, some articles have links to relevant goods and services; buying through them will not cost you more. And if you like programming swag, please visit the TuringTacoTales Store on Redbubble.

Take a look. Maybe you can find something you like: