Kotlin is a modern programming language that compiles to Java bytecode. It is free and open source, and promises to make coding for Android even more fun.
In the previous article, you learned about variables, simple types, arrays, comments and type inference in Kotlin. In this tutorial, we'll continue to learn the language by looking at nullability, loops, and conditions in Kotlin.
1. Nullability
If you're an Android coder, you must have come across the infamous NullPointerException
errors in your app. These happen whenever you try to call a method or read a property of an object reference which is null
. The good news is that Kotlin can help us avoid these kind of errors we get because its a null safe language. That means variables can't have the value null unless you explicitly declare their type to be nullable. In other words, by default, types cannot be null. Let's see how this feature of Kotlin can help us avoid errors in our code.
val name: String = null // will not compile
As you can see above, if we assign null
to the name
variable, the compiler will complain. For the compiler to allow the assignment, declare name as a nullable by adding ?
after the type.
val name: String? = null // will compile name = "Chike" // new value is "Chike"
Note that if ?
is inserted after any type name, we have explicitly instructed the compiler that the value of the type can either store an object reference or can be null
—it is nullable. Here we did so with the String
type, it works the same with Int?
, Byte?
, Long?
, MyClass?
, and so on.
The safe call operator: ?.
Let's learn more about null-safety works in Kotlin with an operator called the safe call operator ?.
.
var name: String? = null print(name.length) // will not compile
The code above won't compile because Kotlin is a null-safe language. The variable name
is assigned the value null
. Now, invoking the property length
on that variable would trigger a NullPointerException
error in Java. But the Kotlin compiler won't allow the invocation of this property because the variable could be null
. The compiler won't allow us to do something that could generate a NullPointerException
!
val v: String? = null print(v?.length) // will compile and print "null"
Now by adding the safe call operator ?.
to the variable before invoking the property, we have explicitly instructed the compiler to invoke the property only if the value isn't null
. If the value is null
, the compiler will use the string "null"
as the value for us. This works also for methods and not just properties.
When you call a method of a nullable, the return type will also be nullable. So, for example the return type of the v?.length
expression when v
is nullable will be Int?
.
val v: String? = null val len: Int? = v?.length print(len) // will compile and print "null"
To bypass nullability checking by the Kotlin compiler, we can replace the ?.
operator with !!.
. This is not recommended though, because of the high probability for getting NullPointerException
errors if used.
val v: String? = null val len: Int? = v!!.length print(len) // triggers a NullPointerException error
The Elvis operator: ?:
This operator ?:
is called the Elvis operator (because its shape looks like Elvis' head). It is used to provide an alternative value for the variable if it is null
.
val username = null val name: String = username ?: "No name" print(name) // will compile and print "No name"
Here, the compiler assigned the string "No name"
to the variable name
, because the first value username is null
. If the first value was not null
, then that value would be assigned to the variable instead.
2. Loops
Kotlin has while, do-while, and for loops.
The while
Loop
A repetition statement allows us to specify that code should repeat an action while some condition remains true.
So in Kotlin, using the while
loop is same as in other languages such as Java.
while (condition) { // execute code here } while (fuel > 5) { driveMeAroundLagos() }
As long as the condition is true, the code inside the curly braces or the loop's body will be executed. If the condition is false, then the code will not be executed. In our example above, once the fuel variable becomes less than 5 litres, the condition becomes false and then the loop terminates. In other words, driveMeAroundLagos()
method execution stops.
The do..while
Loop
Kotlin also has the do..while
loop construct.
do { // execute code here } while (condition)
This is similar to the while
statement. In the while loop, the program tests the loop condition at the beginning of the loop before executing the loop's body. If the condition is false, the body is not executed. But the do-while
loop tests the condition after executing the loop's body. This means that the body is executed at least once.
The for
Loop
A for
loop is a repetition statement that enables us to iterate over objects while a given condition is true.
for (value in range) { // Execute code }
In Kotlin, the for
loop construct works with iteration over ranges, collections, or other iterables (I'll explain more about these in the next post). For loops work together with the in
operator, which is used to ascertain whether a value is present in a given range.
for (a in 1..5) { print("$a ") // will print 1 2 3 4 5 }
In the code above, we are iterating through a closed range 1 to 5 and print out each value in the range.
Iterating Over an Index Array
We can use the withIndex()
function or the indices
property on an array to iterate over an array where we need the index for each element.
Using withIndex()
Function
We can iterate over an array to access each element's index by calling the withIndex()
function on the array, because the withIndex()
function returns an iterable of IndexedValue
type for each element. This lets us access both the index and value for each element from it.
val numbersArray = intArrayOf(1,2,3,4,5) for ((index, value) in numbersArray.withIndex()) { print("$index index value is $value\n") }
The code above will print out the result below:
0 index value is 1 1 index value is 2 2 index value is 3 3 index value is 4 4 index value is 5
Using the indices
Property
Moreover, we can use the indices
property on the array. This will return just the range of valid indices for the array.
val numbers1 = intArrayOf(1,2,3,4,5) for (index in numbers1.indices) { print("$index index value is ${numbers1[index]}\n") }
The above code will produce the same result as the previous example. You can see here also that we can use the index to access an array element, similarly to other programming languages like Java.
3. Conditions
Kotlin has three types of condition statements - the if
, if..else
, and when
statements.
The if
Statement
An if
statement runs some code if a condition is true, or simply skips it, if the condition is false. Nothing special here, if
statements work similarly to the way they do in most other programming languages, including Java.
val number = 20 if (number % 2 == 0) { print("$number is divisible by 2") // 20 is divisible by 2 }
We can also check whether a variable is of a particular type using the is
keyword.
if (number is Int) { print("$number is an integer") }
The if..else
statement
The if..else
performs one action if the condition is true and performs a different action if the condition is false.
val number = 13 if (number % 2 == 0) { print("$number is divisible by 2") } else { print("$number is not divisible by 2") // 13 is not divisible by 2 }
One major feature that distinguishes the if..else
statement in Kotlin from other programming languages such as Java, is the ability to assign a variable from the returned value of the if..else
statement. This is possible because an if..else
statement can be used not just as a statement, but also as an expression in Kotlin.
val number = 13 val result = if (number % 2 == 0) { "$number is divisible by 2" } else { "$number is not divisible by 2" } print(result) // 13 is not divisible by 2
In the code above, we assigned the result
variable with a String
object based on the condition of the if..else
statement. Be aware that this will return only the last statement in a particular condition block and also that you can't use an if
without an else
as an expression.
val result = if (number % 2 == 0) { "Divisible by 2" "Number is $number" // only this string is returned if executed } else { "Not divisible by 2" "Number is $number" }
The when
expression
Kotlin introduced the when
construct as a replacement to the familiar switch
statement we have in different programming languages such as C++, Java and so on. when
is more concise and has more powerful features than the switch
statement you might be familiar with.
The when
statement performs different actions based on the possible values of a constant of type Int
, String
, Byte
or Short
or any other object.
fun guessTheNumber(number: Int) { when (number) { 1 -> println("number is 1") 2 -> println("number is 2") 3 -> println("number is 3") else -> println("number is neither 1, 2 or 3") } }
In the code above, we passed the function guessTheNumber()
a number parameter (we'll discuss functions in Kotlin in a later post). The when
expression then checks if any of the branches match the value of number
and then executes the action on that branch. If none of the branches was a match, the else
branch is executed.
Another variant of the when
expression does not require any argument, like in the example below.
fun guessTheNumber(number: Int) { when { number == 1 -> println("number is 1") number == 2 -> println("number is 2") number == 3 -> println("number is 3") else -> println("number is neither 1, 2 or 3") } }
If we want to execute more than one action on a branch, we need to wrap the actions in curly braces {}
.
val number = 2 when (number) { 1 -> println("number is 1") 2 -> { // block of code executed println("number is 2") println("it is an even number") } 3 -> println("number is 3") }
Moreover, we can combine test values in a single branch.
val number = 2 when (number) { 1, 2 -> println("number is either 1 or 2") // number is either 1 or 2 3 -> println("number is 3") }
Here the first branch is executed because we are testing for a value of either 1 or 2.
Conclusion
In this tutorial, you learned about nullability, loops, and conditions in the Kotlin programming language. In the next tutorial in the Kotlin From Scratch series, you'll learn about the ranges and collections API in Kotlin. See you soon!
To learn more about the Kotlin language, I recommend visiting the Kotlin documentation. Or check out some of our other Kotlin tutorials here on Envato Tuts+!
- Android SDKQuick Tip: Write Cleaner Code With Kotlin SAM Conversions
- Android StudioCoding Functional Android Apps in Kotlin: Getting Started
- Android SDKJava vs. Kotlin: Should You Be Using Kotlin for Android Development?