The Programmers Guide To Kotlin - The Basics
Written by Mike James   
Monday, 01 August 2022
Article Index
The Programmers Guide To Kotlin - The Basics
Semicolons
Var & Val
Null Safety

Null Safety

One of the most important features of Kotlin is that it eliminates the null reference error and you can’t meet null safety early enough.

References can be either non-nullable or nullable.

If you declare a variable in the usual way you get a non-nullable:

var myVariable:sometype = something

and you cannot set the variable to null as:

myVariable = null

throws a compiler error.

The compiler tracks operations that could generate a null, and flags any operation that could possibly set a non-nullable variable to null. For example, if a function could return a null, you cannot assign it to a non-nullable.
This often occurs if you are trying to use a Java function which, of course, doesn’t support non-nullable types.

If you need a nullable reference then you have to explicitly declare it using ? as in:

var myVariable:sometype? = something

Now myVariable can be set to null, i.e.:

myVariable = null

works without a compiler error or warning.

To avoid accidentally using a null reference the compiler will throw an error if you try to use a nullable without first checking that it is non-null.
For example:

var a:Int = 1
var b = a+1

works without any problems as a can never be null as it is a non-nullable, but:

var a:Int? = 1
var b = a + 1

generates a compiler error because you are adding one to a without checking that it isn't null.

 

To use a nullable variable you can test for null using an if statement:

 var a: Int? = 1
 var b:Int = 1
 if(a! = null){
     b = a+1
 }

This compiles and you can be sure that a isn't null when the addition is performed.

Alternatively, if you are accessing a property then you can use the safe call operator ?.

For example:

var b = a?.plus(1)

Here, if a isn't null then b is set to 2, but if a is null then b is set to null.

There are a few small things to notice about this example – by type inference b is a nullable type:

var b:Int? = a?.plus(1)

and nullable simple types are "boxed". That is, the integer a is a full object with methods and properties. In this case we use the plus infix function rather than an operator so that we can use the safe call operator.

If you only want to perform an operation if something is non-null you can use the let method:

a?.let { println(a)}

the block of code in the curly brackets is only executed if a is non-null.
Note: the block of code is a lambda function.

There is also the cutely named Elvis operator ?: which will replace a null value with something that is non-null. For example:

println(a?:0)

will display the value of a if it is non-null and 0 otherwise.

Finally, if you want to throw a null reference exception you can force one using !!. For example:

println(a!!)

will either print the value of a, or throw an exception if a is null. My guess is that you would only use this to test things.

These null handling features make null a useful, rather than a dangerous, value. For example, if you cast something to a different type you will generate a classcastException if it isn't possible. It is much safer to use the safe cast as? which will return null if the cast isn't possible.

So:

variable as? type

will evaluate to null if the cast to type isn't possible.

The advantage of generating a null is that you now have lots of ways of working with it that are guaranteed not to end in an exception.

Notice that a great deal of what makes the Kotlin null-safe is provided by the compiler, which does its best not to let you write code that works with null values that could result in an exception.

If the compiler flags a null problem then don't just make the simplest fix. Try to work out what the role of the null is and whether you need it at all. Using non-nullable values is still the safest option.

Summary

  • In Kotlin, functions are entities in their own right and not relegated to just being methods within classes. However, to retain Java compatibility at compile time, they are represented as methods in generated classes.

  • The semicolon is rarely needed to mark the end of an instruction. Semicolon inference means that you only have to use one when the compiler detects an ambiguity in what you have entered.

  • Multiple instructions can be placed on a single line separated by semicolons and you can spread an instruction across multiple lines as long as you don’t split a keyword.

  • Lambdas and anonymous functions make it easy to pass functions as parameters to other functions.

  • Infix function calls can make some common expressions look different from their Java equivalents.

  • Variables can be declared using var when they are read/write or using val when they are read-only.

  • A val is read-only with respect to its contents, but any object it references may still be mutable.

  • Kotlin supports the same simple or primitive types that Java does, but many of its operators use an infix function notation.

  • Null safety is an important and useful feature of Kotlin. Types can be nullable or non-nullable.

  • You cannot store any value which could be potentially null in a non-nullable type and the compiler flags an error if you try.

  • Nullable types can be set to null but the compiler will not let you use them unless you have checked that they are non-null.

  • There are a range of null-protected operators that make working with nullable types safer:

    safe call operator object?.method returns null if the object reference is null

    Elvis operator variable?:value replaces a null variable with a specified non-null value

    safe cast operator object as? type returns null if the object cannot be cast to type

    null reference operator !! throws a null pointer exception

This article is an extract from: 

Programmer's Guide To Kotlin Third Edition

kotlin3e360

You can buy it from: Amazon

Contents

  1. What makes Kotlin Special
  2. The Basics:Variables,Primitive Types and Functions 
  3. Control
         Extract: If and When 
  4. Strings and Arrays
  5. The Class & The Object ***NEW!
  6. Inheritance
  7. The Type Hierarchy
  8. Generics
  9. Collections, Iterators, Sequences & Ranges
        Extract: Iterators & Sequences 
  10. Advanced functions 
  11. Anonymous, Lamdas & Inline Functions
  12. Data classes, enums and destructuring
        Extract: Destructuring 
  13. Exceptions, Annotations & Reflection
  14. Coroutines
        Extract: Coroutines 
  15. Working with Java
        Extract: Using Swing
  16. Compose Multiplatform
        Extract: Compose Layout 

<ASIN:B0D8H4N8SK>

 kotlinlogo

To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.

Banner


Microsoft Introduces Unified .NET API For AI
14/10/2024

Microsoft has introduced new libraries for integrating AI services into .NET applications and libraries, along with middleware for adding key capabilities.



Java Version 23 Released
30/09/2024

It was in April 2024 that we had Java 22. Now after just 6 months there's version 23, which is a STS release with lots of features in preview status.


More News

espbook

 

Comments




or email your comment to: comments@i-programmer.info

 



Last Updated ( Tuesday, 02 August 2022 )