This information is a collection of my notes from taking Google’s Kotlin Bootcamp for Programmers course.
Types
Kotlin has 4 numerical types: Int, Long, Float, and Double. Math with Ints returns an Int, Math with any decimal numbers returns decimal numbers. Kotlin will autobox, and you can call methods like add, minus, div, and times:
4.times(5) = 20
You can use underscores in numbers to make them more readable:
1_000_000
Cast with myVar.toType():
newInt = oldByte.toInt()
Kotlin is strongly typed, but you do not have to declare the type since the compiler can usually figure out the type. Both of the declarations below are valid and are equivalent:
var i : Int = 2;
var i = 2;
Variables
val – Once declared you cannot change the value.
var – Variables declared with var can be reassigned.
Variable Interpolation is useful when working with Strings. Insert $variableName inside a String, and it will be replaced with its value. You can also include expressions to be evaluated inside curly braces:
"Hello $name, nice to meet you."
"We have ${numDogs + numCats} pets."
Comparison
Comparison in Kotlin is similar to Java. Addtionally, you can check ranges:
if (x in 1..100)
Use “when” like a switch statement. Note that “break” is not necessary and “else” is optional (similar to “default” in a switch statement):
when (numberOfCats) {
0 -> println("Sorry")
1 -> println("Not enough")
in 2..7 -> println("Just right")
else -> println("Too many")
}
Nullability
By default variables cannot be null. If you are not initializing them with a value, you can use the “?” to indicate the variable can be null:
var num: Int? = null
Instead of checking for null explicitly before calling a method on a variable, instead you can use the “?” operator:
num = num?.dec()
Similarly, you can chain null tests with the Elvis operator “?:”. This is like saying, if value is not null do one thing, if it is null do the other thing:
num = num?.dec() ?: 0 // decrements num if non null, sets num to 0 if it is null
The “not null assertion opertator” or “double bang”, “!!”, let’s you throw a NullPointerException when a value is null:
val len = name!!.length // throws NPE is name is null
Arrays & Lists
Create an immutable list with listOf:
val myList = listOf("item1", "item2", "item3")
Create a mutable list with mutableListOf:
val myList = mutableListOf("item1", "item2", "item3")
myList.remove("item2");
Arrays are immutable only. Once created, you cannot add or remove items – but you can still change the values of the elements. Use Arrays.toString to print the array. This is not necessary for lists.
val myArray = arrayOf("item1", "item2", "item3")
println(java.util.Arrays.toString(myArray));
With arrays you can mix type, or declare an array of a defined type:
val mixed = arrayOf("Item1", 2, true)
)
val intArr = intArrayOf(1, 2, 3
Arrays can be combined with “+”:
val newArr = arr1 + arr2
You can initialize arrays with code, where “it” is the index. In the example below we initialize an array of length 5 with values equal to the index * 3:
val newArr = Array(5) {it * 3}
Loops
There are many ways to loop through lists and arrays using for loops:
for (element in myArray) {...}
for ((index, element) in myArray.withIndex()) {...}
for (i in 1..5) {...}
for (i in 10 downTo 1) {...}
for (i in 4..10 step 2) {...}
for (i in 'a'..'z') {...}
Kotlin has traditional while & do while loops. It also has repeat loops:
repeat(xTimes) {...}
Functions
main is declared like so – note how arrays are declared and how they are used.
fun main(args: Array<String>) {
println("Hello, ${args[0]}")
}
You can assign an expression to a variable.
// This line prints & assigns kotlin.Unit to the variable
val isUnit = println("This is an expression")
// This line prints kotlin.Unit
println(isUnit)
Parameters can have default values. You can skip passing in those arguments, override the default value, or assign the value by name. You can also use a function as a default value.
fun swim(speed: String = "fast", funParam: String = getFunParam()) {
println("swimming $speed")
}
swim()
swim("slow")
swim(speed = "medium")
Single expression functions are like lambdas in that it’s a shorter syntax where you can omit the curly braces and return statement.
fun isTooHot(temperature: Int) = temperature > 30
fun isDirty(dirty: Int) = dirty > 30
fun isSunday(day: String) = day == "Sunday"
Lambdas
Lambdas can be assigned to variables and then used like functions.
var dirtyLevel = 20;
val filterWaterLambda = {dirt: Int -> dirt / 2}
filterWaterLambda(dirtyLevel)
Function Types
val filterWaterFunction : (Int) -> Int = {dirt -> dirt / 2}
In the code above we’re setting filterWaterFunction equal to a function that takes an Int as a parameter and returns an it. After the equals sign is the lambda that defines the function. Unlike the lambda above, we don’t have to specify the type for “dirt” (but we can).
Higher Order Functions
A higher order function can take another function as an argument.
fun updateDirty(dirty: Int, operation: (Int) -> Int) : Int {
)
return operation(dirty)
}
val operation: (Int) -> Int = {dirty -> dirty / 2}
// call the higher order function with a lambda
println( updateDirty(20, operation))
// call the higher order function with a regular function
fun increaseDirty(start: Int) : Int {
return start + 1
}
println(updateDirty(20, ::increaseDirty)
Last Parameter Call Syntax
Kotlin prefers for parameters that take functions to be the last parameter. In this case you can pass a lambda outside parentheses.
var dirtyLevel = 19
dirtyLevel = updateDirty(dirtyLevel) {dirty -> dirty + 5}
println(dirtyLevel)
Constructors
Define a constructor like a function to pass in parameters. Or define fields in the constructor. Additional initialization takes place in init blocks
// Parameters, they can only be seen when initializing fields or in init blocks
Aquarium(length :Int = 20, width: Int = 30, height: Int = 40)
// Fields, they can be seen anywhere in the class
Aquarium(var length:Int = 20, var width: Int = 30, var height: Int = 40)init{
println("$length")
}