The Kotlin programming language uses the question mark (?
) symbol for many of its null safety features.
Null safety is a feature of modern programming languages created to reduce (or eliminate) the danger of referencing null values in your source code.
To understand how Kotlin null safety feature works, let’s see an example in Java first.
The following code is valid in Java:
class Example {
public static void main(String[] args) {
String myString = null;
myString.length();
}
}
But when you run the code above, the call to myString.length()
will produce an error as shown below:
Exception in thread "main" java.lang.NullPointerException
at Example.main(example.java:4)
The NullPointerException
happens because the value of the myString
variable above is null
, and that null
value doesn’t have access to the .length()
method.
Kotlin was designed to prevent the NullPointerException
error, that’s the reason the null safety feature was added to the language.
In Kotlin, you can’t assign null
to a variable with String
type as shown below:
var myString: String = null
// Error: null can not be a value of non-null String type
To allow null
in your variable, you need to add a question mark ?
after the variable type:
var myString: String? = null
The variable then becomes a nullable String
type, which can hold the null
value.
This different type between String
and String?
also allows the Kotlin compiler to report any null
related error in your source code before you run it.
For example, suppose you want to check the length
of the String?
type. By default, Kotlin will complain saying that you need to perform a safe call:
var myString: String? = null
myString.length // Error: only safe or asserted call allowed!
A safe call for a nullable type is done by adding a question mark before the property or method call.
Consider the following example:
var myString: String? = null
myString?.length // ok
myString?.uppercase() // ok
Both property and method calls in the code above are safe calls. When the value of the variable is null
, then Kotlin simply returns null
without executing the property or method calls.
non-null asserted call to properties and methods
Besides the safe call above, Kotlin also has the non-null asserted call that uses the double bang operator (!!
)
The non-null asserted call is used when you are absolutely certain that the nullable type is not null
, so you don’t need a safe call.
Consider the following example:
var myString: String? = null
myString = "abc"
myString!!.length
myString!!.uppercase()
You can see that by the time the .length
and .uppercase()
are called, the value of myString
is already not null
.
But Kotlin still complains that you need to either do a safe call or an asserted call because of the nullable String?
type.
Because we know for sure that the myString
value is abc
, you can do a non-null asserted call using the !!
operator.
When you do a non-null asserted call to a variable with null
value, Kotlin will throw the NullPointerException
error:
var myString: String? = null
myString!!.length // Error: NullPointerException
As you can see, the question mark in Kotlin is a great feature that helps you avoid errors caused by the null
values.
Question mark for safe casts
The question mark can also be used when casting a variable using the as
keyword:
var myVar: Any = "String"
var myInt: Int? = myVar as? Int // returns null
When the casting is not possible, then Kotlin will return null
instead of throwing ClassCastException
.
The question mark in elvis operator
Finally, the question mark is also used in the Kotlin elvis operator (?:
) to write a conditional expression:
var myStr: String? = null
var myVar: String = myStr ?: "Hello"
You can learn more about the elvis operator here.
Now you’ve learned how the question mark is used in Kotlin for null safety features. Nice work! 👍