Nullability in Java and Kotlin
Nullability is the ability of a variable to hold a
null value. When a variable contains
null, an attempt to dereference the variable leads to a
NullPointerException. There are many ways to write code in order to minimize the probability of receiving null pointer exceptions.
This guide covers differences between Java's and Kotlin's approaches to handling possibly nullable variables. It will help you migrate from Java to Kotlin and write your code in authentic Kotlin style.
The first part of this guide covers the most important difference – support for nullable types in Kotlin and how Kotlin processes types from Java code. The second part, starting from Checking the result of a function call, examines several specific cases to explain certain differences.
Support for nullable types
The most important difference between Kotlin's and Java's type systems is Kotlin's explicit support for nullable types. It is a way to indicate which variables can possibly hold a
null value. If a variable can be
null, it's not safe to call a method on the variable because this can cause a
NullPointerException. Kotlin prohibits such calls at compile time and thereby prevents lots of possible exceptions. At runtime, objects of nullable types and objects of non-nullable types are treated the same: A nullable type isn't a wrapper for a non-nullable type. All checks are performed at compile time. That means there's almost no runtime overhead for working with nullable types in Kotlin.
In Java, if you don't write null checks, methods may throw a
This call will have the following output:
In Kotlin, all regular types are non-nullable by default unless you explicitly mark them as nullable. If you don't expect
a to be
null, declare the
stringLength() function as follows:
a has the
String type, which in Kotlin means it must always contain a
String instance and it cannot contain
null. Nullable types in Kotlin are marked with a question mark
?, for example,
String?. The situation with a
NullPointerException at runtime is impossible if
String because the compiler enforces the rule that all arguments of
stringLength() not be
An attempt to pass a
null value to the
stringLength(a: String) function will result in a compile-time error, "Null can not be a value of a non-null type String":
If you want to use this function with any arguments, including
null, use a question mark after the argument type
String? and check inside the function body to ensure that the value of the argument is not
After the check is passed successfully, the compiler treats the variable as if it were of the non-nullable type
String in the scope where the compiler performs the check.
You can write the same shorter – use the safe-call operator ?. (If-not-null shorthand), which allows you to combine a null check and a method call into a single operation:
In Java, you can use annotations showing whether a variable can or cannot be
null. Such annotations aren't part of the standard library, but you can add them separately. For example, you can use the JetBrains annotations
@NotNull (from the
org.jetbrains.annotations package) or annotations from Eclipse (
org.eclipse.jdt.annotation). Kotlin can recognize such annotations when you're calling Java code from Kotlin code and will treat types according to their annotations.
If your Java code doesn't have these annotations, then Kotlin will treat Java types as platform types. But since Kotlin doesn't have nullability information for such types, its compiler will allow all operations on them. You will need to decide whether to perform null checks, because:
Just as in Java, you'll get a
NullPointerExceptionif you try to perform an operation on
The compiler won't highlight any redundant null checks, which it normally does when you perform a null-safe operation on a value of a non-nullable type.
Learn more about calling Java from Kotlin in regard to null-safety and platform types.
Support for definitely non-nullable types
In Kotlin, if you want to override a Java method that contains
@NotNull as an argument, you need Kotlin's definitely non-nullable types.
For example, consider this
load() method in Java:
To override the
load() method in Kotlin successfully, you need
T1 to be declared as definitely non-nullable (
T1 & Any):
Learn more about generic types that are definitely non-nullable.
Checking the result of a function call
One of the most common situations where you need to check for
null is when you obtain a result from a function call.
In the following example, there are two classes,
Order has a reference to an instance of
findOrder() function returns an instance of the
Order class, or
null if it can't find the order. The objective is to process the customer instance of the retrieved order.
Here are the classes in Java:
In Java, call the function and do an if-not-null check on the result to proceed with the dereferencing of the required property:
Converting the Java code above to Kotlin code directly results in the following:
Here is a shorter version of the same:
Default values instead of null
null is often used in combination with setting the default value in case the null check is successful.
The Java code with a null check:
To express the same in Kotlin, use the Elvis operator (If-not-null-else shorthand):
Functions returning a value or null
In Java, you need to be careful when working with list elements. You should always check whether an element exists at an index before you attempt to use the element:
The Kotlin standard library often provides functions whose names indicate whether they can possibly return a
null value. This is especially common in the collections API:
When you need to get the biggest element or
null if there are no elements, in Java you would use the Stream API:
In Kotlin, use aggregate operations:
Learn more about collections in Java and Kotlin.
Casting types safely
When you need to safely cast a type, in Java you would use the
instanceof operator and then check how well it worked:
To avoid exceptions in Kotlin, use the safe cast operator
as?, which returns
null on failure:
Browse other Kotlin idioms.
Learn how to convert existing Java code to Kotlin with the Java-to-Kotlin (J2K) converter.
Check out other migration guides:
If you have a favorite idiom, feel free to share it with us by sending a pull request!