Course Content
Android Development with Kotlin
Android Development with Kotlin
Null Safety and Safe Calls
In Kotlin, as in any other programming language, there are empty variables or objects. For example, let's say we have a variable "name
," and the user has not filled in this field. In this case, the variable will hold the value null
.
Null
In programming, null
represents a special value that indicates the absence of any value or object. This means that a variable containing null
does not reference any object in memory. Null
is used to indicate that a variable is either uninitialized or explicitly holds no value.
Null is a common cause of many errors, and in this chapter, we will learn how to work with this emptiness inside variables or objects properly!
Nullable Types and the `?` Operator
In Kotlin, types are non-nullable by default, which means you cannot assign a null
value to a variable of a non-nullable type. To declare a variable that can hold a null value, you use the ?
operator.
Here’s how it looks in the code:
Main
fun main() { var nonNullableString: String = "Hello" nonNullableString = null // This would cause a compile-time error var nullableString: String? = "Hello" nullableString = null // This is allowed println(nullableString) }
As you can see, when we run the code, we get an error telling us that we cannot assign null
to a non-nullable type String.
However, below that, we define a new variable with the data type String?
, which allows us to assign null
without any errors. This way, Kotlin helps us control the values of the variables we work with.
So, to make it possible to create variables that can hold null
, we need to add the ?
symbol to the data type when declaring the variable.
Let's comment out the line that causes the error and look at the result:
Main
fun main() { var nonNullableString: String = "Hello" //nonNullableString = null // This would cause a compile-time error var nullableString: String? = "Hello" nullableString = null // This is allowed println(nullableString) }
Don't forget to mark variables that can hold a null
value with the special symbol in your program!
Safe Calls and the Elvis Operator
You cannot call methods or access certain properties on variables or objects that can hold a null
value. For this, there are safe calls, which are also done using the ?
symbol.
Let's first look at a situation where we attempt to call the .length
property on a string variable that contains a null
value.
Note
The
length
property returns the length of the string, which is the number of characters in the string. For example, the string "Hello" has 5 elements, with each letter/symbol in the word being counted as a separate element.
Main
fun main() { var nullableString: String? = "Hello" println(nullableString.length) }
As you can see, the compiler tells us that we can only use safe calls because you cannot use properties or methods on a variable that MIGHT contain a null
value.
Let's call this property using a safe call with the ?.
syntax:
Main
fun main() { var nullableString: String? = "Hello" println(nullableString?.length) }
To call a property or method on a variable that might contain null
, we use the following syntax:
variableThatMightContainANull?.property
This way, it will be a safe call that will return null if the variable contains null
, instead of throwing an error or exception when accessing any property:
Main
fun main() { var nullableString: String? = "Hello" nullableString = null println(nullableString?.length) }
There's also a way to handle a null
value using a regular if-else
statement.
It will look like this:
Main
fun main() { var nullableString: String? = "Hello" nullableString = null if (nullableString != null) { println(nullableString.length) } else { println("nullableString is null") } }
In the code example above, we prevent performing operations on a variable that might be null
.
The Elvis Operator
The Elvis operator ?:
is used to provide a default value when the expression on the left-hand side is null
.
Let's look at a code example where we try to assign the length of a string, which might be null
, to a variable:
Main
fun main() { var nullableString: String? = "Hello" //nullableString = null val length: Int = nullableString?.length ?: 0 println(length) }
In the code above, we try to get the length of a string, but if the value of that string is null
, we assign the variable length
a value of 0.
When you run the code, you'll see the value 5
, which is the length of the string "Hello
."
But let's uncomment the line that sets the nullableString
variable to null
and see the result:
Main
fun main() { var nullableString: String? = "Hello" nullableString = null val length: Int = nullableString?.length ?: 0 println(length) }
As you can see, instead of null
, we get 0, which we specified in the Elvis operator.
Note
When using the Elvis operator, we still need to use the safe call operator; otherwise, the compiler will not allow us to call properties or methods on a variable that might contain null.
Non-Null Assertions
And the last thing we'll look at in this chapter is Non-Null Assertions.
This is used when a variable that MIGHT hold a null value is definitely not null (or you believe it isn't).
Here's how to use such an assertion:
Main
fun main() { var nullableString: String? = "Hello" //nullableString = null val length: Int = nullableString!!.length println(length) }
If the value is null
, it throws a NullPointerException
:
Main
fun main() { var nullableString: String? = "Hello" nullableString = null val length: Int = nullableString!!.length println(length) }
Use the non-null assertion operator with caution, as it can lead to runtime exceptions if the value is actually null
.
Summary
Let's summarize briefly:
- To allow a variable to hold a null value (making it nullable), you need to add a question mark when declaring the type:
String?
. - To use a safe call, you add a question mark after the variable name when attempting to call a method or property:
variable?.property
. - If you want to assign a specific value when the variable is null, you can use the Elvis operator:
length = nullableString?.length ?: 0
. - If you're certain that the variable is not null, you can use a non-null assertion:
length = nullableString!!.length
, but be cautious as this can lead to many errors!
Thanks for your feedback!