If you have got been programming in Java or the other language that has the thought of null reference then you need to have detected regarding or seasoned NullPointerException in your programs.
NullPointerExceptions are Runtime Exceptions that are threw by the program at runtime inflicting application failure and system crashes.
Wouldn’t it’s nice if we have a tendency to might notice doable NullPointerException exception errors at compile time itself and guard against them?
Well, Enter Kotlin!
Nullability and Nullable varieties in Kotlin
Kotlin supports nullability as a part of its sort System. meaning you have got the power to declare whether or not a variable will hold a null worth or not.
By supporting nullability within the sort system, the compiler will notice doable NullPointerException errors at compile time and cut back the chance of getting them thrown at runtime.
Let’s perceive however it works!
All variables in Kotlin are non-nullable by default. therefore If you are attempting to assign a null worth to an everyday variable, the compiler can throw a slip-up –
var greeting: String = "Hello, World" greeting = null // Compilation Error
To allow null values, you have got to declare a variable as nullable by appending a matter mark in its sort declaration –
var nullableGreeting: String? = "Hello, World" nullableGreeting = null // Works
We know that NullPointerException happens after we attempt to decision a technique or access a property on a variable that is null. Kotlin disallows methodology calls and property access on nullable variables and thereby prevents several doable NullPointerExceptions.
For example, the subsequent methodology access works as a result of Kotlin is aware of that the variable salutation will ne’er be null –
val len = salutation.length val higher = salutation.toUpperCase()
But constant methodology decision won’t work with nullable Greeting variable –
val len = nullableGreeting.length // Compilation Error val higher = nullableGreeting.toUpperCase() // Compilation Error
Since Kotlin is aware of beforehand that variable are often null and that cannot, It will notice and command calls that might lead to NullPointerException at compile-time itself.
Working with Nullable varieties
All right, It’s nice that Kotlin disallows methodology calls and property access on nullable variables to protect against NullPointerException errors. however we have a tendency to still ought to do this right?
Well, There are many ways in which of safely doing that in Kotlin.
1. Adding a null Check
The most trivial thanks to work with nullable variables is to perform a null check before accessing a property or occupation a technique on them –
val nullableName: String? = "John" if(nullableName != null) { println("Hello, ${nullableName.toUpperCase()}.") println("Your name is ${nullableName.length} characters long.") } else { println("Hello, Guest") }
Once you perform a null comparison, the compiler remembers that and permits calls to toUpperCase() and length within the if branch.
2. Safe call operator: ?
Null Comparisons are straightforward however too long-winded. Kotlin provides a secure decision operator, ?. that reduces this verboseness. It permits you to mix a null-check and a technique decision in a very single expression.
For example, the subsequent expression –
nullableName?.toUpperCase()
is same as –
if(nullableName != null) nullableName.toUpperCase() else null
Wow! That saves tons of keystrokes, right? 🙂
So if you were to print the name in majuscule and its length safely, you’ll do the subsequent –
val nullableName: String? = null println(nullableName?.toUpperCase()) println(nullableName?.length) // Prints null null
That written null since the variable nullableName is null, otherwise, it might have written the name in majuscule and its length.
But what if you don’t wish to print something if the variable is null?
Well, To perform an
val nullableName: String? = null nullableName?.let { println(it.toUpperCase()) } nullableName?.let { println(it.length) } // Prints nothing
The lambda expression within let is dead on condition that the variable nullableName isn’t null.
That’s nice however that’s not all. Safe decision operator is even additional powerful than you think that. as example, you’ll chain multiple safe calls like this –
val currentCity: String? = user?.address?.city
The variable currentCity are null if any of user, address or town is null.
3. Elvis operator: ?:
The elvis operator is employed to supply a default worth once the initial variable is null –
val name = nullableName ?: "Guest"
The higher than expression is same as –
val name = if(nullableName != null) nullableName else "Guest"
In different words, The elvis operator takes 2 worths and returns the primary value if it’s not null, otherwise, it returns the second worth.
The elvis operator is usually used with Safe decision operator to supply a default worth apart from null once the variable on that a way or property is termed is null –
val len = nullableName?.length ?: -1
You can have a lot of complicated expressions on the left aspect of elvis operator –
val currentCity = user?.address?.city ?: "Unknown"
Moreover, you’ll use throw-and-come expressions on the correct aspect of loony toons operator. this is often terribly helpful whereas checking preconditions during a operation. therefore rather than providing a default worth within the right aspect of Elvis operator, you’ll throw Associate in Nursing exception like this –
val name = nullableName ?: throw IllegalArgumentException("Name cannot be null")
4. Not null assertion : !! Operator
The !! operator converts a nullable sort to a non-null sort, and throws a NullPointerException if the nullable sort holds a null worth.
So It’s how of soliciting for NullPointerException expressly. Please don’t use this operator.
val nullableName: String? = null nullableName!!.toUpperCase() // ends up in NullPointerException
Null Safety and Java ability
Kotlin is totally practical with Java however Java doesn’t support nullability in its sort system. therefore what happens after you decide Java code from Kotlin?
Well, Java types area unit treated specially in Kotlin. they’re known as Platform varieties. Since Kotlin doesn’t have any info regarding the nullability of a kind declared in Java, It relaxes compile-time null checks for these types.
So you don’t get any null safety guarantee for varieties declared in Java, and you have got full responsibility for operations you perform on these varieties. The compiler can permit all operations. If you recognize that the Java variable are often null, you ought to compare it with null before use, otherwise, rather like Java, you’ll get a NullPointerException at runtime if the worth is null.
Consider the following User category declared in Java –
public class User { private final String name; public User(String name) { this.name = name; } public String getName() { return name; } }
Since Kotlin doesn’t comprehend the nullability of the member variable name, It permits all operations on this variable. you’ll treat it as nullable or non-nullable, however the compiler won’t enforce something.
In the following example, we tend to merely treat the variable name as non-nullable and decision strategies and properties on that –
val javaUser = User(null) println(javaUser.name.toUpperCase()) // Allowed (Throws NullPointerException) println(javaUser.name.length) // Allowed (Throws NullPointerException)
The other possibility is to treat the member variable name as nullable and use the safe operator for occupation strategies or accessing properties –
val javaUser = User(null) println(javaUser.name?.toUpperCase()) // Allowed (Prints null) println(javaUser.name?.length) // Allowed (Prints null)
Nullability Annotations
Although Java doesn’t support nullability in its sort system, you’ll use annotations like @Nullable and @NotNull provided by external packages like javax.validation.constraints, org.jetbrains.annotations etc to mark a variable as Nullable or Not-null.
Java compiler doesn’t use these annotations, however these annotations area unit utilized by day, ORM libraries and different external tools to supply help whereas operating with null values.
Kotlin additionally respects these annotations after they area unit gift in Java code. Java varieties that have these nullability annotations area unit depicted as actual nullable or non-null Kotlin varieties rather than platform varieties.
Nullability and Collections
Kotlin’s assortment API is constructed on prime of Java’s assortment API however it totally supports nullability on Collections.
Just as regular variables area unit non-null by default, a standard assortment additionally can’t hold null values –
val regularList: List = listOf(1, 2, null, 3) // Compiler Error
1. Collection of Nullable Types
Here is however you’ll declare a group of Nullable varieties in Kotlin –
val listOfNullableTypes: List = listOf(1, 2, null, 3) // Works
To filter non-null values from an inventory of nullable varieties, you’ll use the filterNotNull() operate –
val notNullList: List = listOfNullableTypes.filterNotNull()
2. Nullable Collection
Note that there’s a distinction between {a assortment|a set|a group} of nullable varieties and a nullable collection.
A collection of nullable varieties will hold null values however the gathering itself can’t be null –
var listOfNullableTypes: List<Int?> = listOf(1, 2, null, 3) // Works listOfNullableTypes = null // Compilation Error
You can declare a nullable assortment like this –
var nullableList: List? = listOf(1, 2, 3) nullableList = null // Works
3. Nullable Collection of Nullable Types
Finally, you’ll declare a nullable assortment of nullable varieties like this –
var nullableListOfNullableTypes: List? = listOf(1, 2, null, 3) // Works nullableListOfNullableTypes = null // Works
Conclusion
That’s all in this article folks. I hope you understood how kotlin helps you avoid NullPointerException errors with its nullable type concept.
Thanks for reading.