Nullable types

When you want to state that a reference type doesn’t point to a memory address, you can assign it a null value. If you have ever used Java, you probably experienced the NullPointerException fail, as it is one of the most common errors. This error is raised by the runtime when you dereference a null variable.

This decision, to have nulls in Java, is criticized a lot and is also sometimes called  a Billion Dollar mistake. The introduction of the optional type in Java 8, tries to address this problem.

Kotlin tries to prevent these mistakes with supporting nullability in its type system. With nullable types, Kotlin tries to prevent null pointer errors during compilation and reduce the possibility of null pointer errors during runtime.

All types in Kotlin can be nullable, and only then can they have a null value assigned. Nullable types are declared with a question mark at the end. First, take a look at this example where the compiler doesn’t allow a non-nullable type to be assigned a null value:

var error: String = null //Compiler error

If you declare your type as nullable, with a question mark, then the compiler allows assigning nulls:

var nullable: String? = null

If you try to access a variable of a nullable type in your source code, the compiler will not allow it, because during compile time we don’t know if this value will be safe to access, that is, not null.

That’s why Kotlin has several operators for dealing with nullable types. The first one is safe call operator ? . It combines a null check and a member access into a single declaration.

First, take a look how would you check, without this operator, if it is safe to access a nullable type:

fun nullCheck(str: String?) {
val upperCase: String? = if (str != null) {
str.toUpperCase()
}
else {
null
}
}

Thanks to safe call operator, this can be done with one line of code:

fun safeCall(str: String?) {
val upperCase: String? = str?.toUpperCase()
}

You can also chain safe call operators, as long they return nullable values:

fun safeCallChaining(str: String?) {
val firstLetterCapitalized: String? = str?.take(1)?.toUpperCase()
}

There is also an operator for making non-null assertions. It is expressed with two exclamation marks, !!, and it converts a nullable type into non-nullable. If you use it on a null value then a null pointer exception is thrown. Take a look at this example: if you pass a string object to this function, it will be printed out in upper case. But when a null value is passed, the runtime throws a KotlinNullPointerException on the first line of the function, when you use the non-null assertion:  

fun nonNullAssertion(str: String?) {
val nonNullString = str!!
val upperCase: String = nonNullString.toUpperCase()
println(upperCase)
}

With this operator, you are in full control of nullability and you are basically telling the compiler I know this value will not be null, give me access to it.

In general, you should you use the safe call operator if you can.

Kotlin also has the so-called Elvis operator ?: which is similar to Java’s ternary operator.

It can only be used on nullable expressions and it is used to provide a default value in case the expression is null. In this example, we want to assign to a local variable string in upper case if it is not null, and if it is null, just an empty string. Instead of using an if-else expression, with the Elvis operator it looks like this:

fun elvisOperator(str: String?) {
val upperCase = str?.toUpperCase() ?: ""
}

Basically what the Elvis operator does is evaluate the left side of the operator. If it is not null, this value is used, if it is null the right side of the operator is evaluated. You can put literals, properties or function calls on the right side . You can also chain them, as this example shows:

fun chainingElvisOperator(first: String?, second:String?) {
val upperCase = first?.toUpperCase() ?: second?.toUpperCase() ?: ""
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.249.202