Kotlin Quick Reference
This reference summarizes the topics covered in the Kotlin Bootcamp course in the form of code
snippets. See the Kotlin Language Documentation for full reference. See the Kotlin Koans for more
snippets to practice with. See the Kotlin Bootcamp course if you need anything explained.
Lesson 0
Lesson 1
Hello Kotlin function
Hello Kotlin program
Operators
Type conversion
Number formatting
val (immutable) & var (mutable)
Nullability
Strings / String Templates
if/else
When
listOf / mutableListOf
arrayOf / mutableArrayOf / intArray…
for loop
for (element in swarm) {...}
Lesson 2
Functions
Compact Functions
Filters
Lambas (anonymous functions)
Higher order functions (fun with fun arg)
Lesson 3
Class
Visibility
Inheritance
Abstract classes
Interfaces
Data Classes
Composition
Singleton / object
enum
Lesson 4
Pairs
Lists
Mapping
Constants
Extension functions
Property extensions
Generic classes
Generics: Full example
Generic constraint
In and Out Types
Generic functions and methods
Inline / reified
Annotations
Reflection
Annotations for getters and setters
Labeled breaks
Lesson 5
Lambda recap
Higher order function
Standard Library: apply & run
Standard Library: with & repeat
Inline
Lambda instead ofSAM
Lesson 0
● Install JDK if you don't have it
● Link to downloading IntelliJ
● Starting the interpreter: Tools > Kotlin > Kotlin REPL
Lesson 1
Hello Kotlin function Hello Kotlin program
fun p rintHello () { fun main (args: Array<String>) {
p rintln ("Hello Kotlin") println("Hello ${args[0]} ")
} }
printHello()
Operators Type conversion
*, fish.times(6) 1.toLong()
/, fish.div(10) 1.toString()
+, fish.plus(3)
-, fish.minus(3)
Number formatting val (immutable) & var (mutable)
neMillion = 1_000_000
val o quarium = "my a
val a quarium"
val s ocialSecurityNumber = 999_99_9999L var f ish = 50
var s nails : Int = 1 2
Nullability Strings / String Templates
var rocks: Int = null //Error "hello" + "fish" + "!"
var marbles: Int? = null "I have $numberOfFish fish"
fishFoodTreats?.dec() "Print ${ numberOfFish + 5 } fish"
"fish" == "fish"
var l otsOfFish: List<String?> = val message = "You are ${ if (length <
l istOf(null, null) 5) "fried" else "safe" } fish"
return fishFoodTreats?.dec() ?:0
goldfish!!.eat
if/else When
if (numberOfFish > numberOfPlants) { when (numberOfFish) {
println("Good ratio!") 0 -> println("Empty tank")
} else { in 1..50 -> println("Got fish!")
println("unhealthy ratio") else -> println("Perfect!")
} }
if (fish in 1..100) println(fish)
val isHot =
if (temperature > 90) true else false
listOf / mutableListOf arrayOf / mutableArrayOf / intArray…
val m yList = val s chool =
m utableListOf("tuna",,"shark") a rrayOf("tuna","salmon","shark")
myList.remove("shark") // OK! val mix = arrayOf("fish", 2)
val swarm = listOf(fish, plants) println(Arrays.toString(intArrayOf(2,
"foo")))
val bigSwarm = arrayOf(swarm,
arrayOf("dolphin","whale","orka"))
val array = Array (5) { it * 2 }
for loop
for (element in swarm) {...}
for ((index, element) in
swarm.withIndex()) {
println("Fish at $index is
$element")
}
for (i in 'b'..'g') print(i)
for (i in 1..5) print(i)
for (i in 5 downTo 1) print(i)
for (i in 3..6 step 2) print(i) //
Prints: 35
Lesson 2
Functions Compact Functions
fun randomDay(): String {return fun isTooHot(temperature: Int) =
"Monday"} temperature > 30
fun fishFood (hour: Int, day: String = fun shouldChangeWater (day: String,
"Tuesday"): String {} temperature: Int = 22, dirty: Int =
20): Boolean {
fun isTooHot(temperature: Int): Boolean return when {
= temperature > 30 isTooHot(temperature)-> true
else -> false
}
}
fun getDirtySensorReading() = return 20
fun shouldChangeWater (day: String,
temperature: Int = 22, dirty: Int =
getDirtySensorReading()) {...}
Filters Lambdas (anonymous functions)
{ println("Hello") }()
println( decorations.filter {it[0] ==
'p'}) val waterFilter = { dirty: I
nt - > dirty
/ 2 }
val waterFilter : (Int) -> I nt = {
dirty -> dirty / 2 }
Higher order functions (fun with fun arg)
fun updateDirty(dirty: Int, operation:
(Int) -> Int): Int {
return operation(dirty)
}
updateDirty(50, ::increaseDirty)
Lesson 3
Class Visibility
class Aquarium(var length: Int = 1 00, package:
var width: Int = 20, var height: I nt = public - default. Everywhere
40) { private - file
internal - module
constructor(numOfFish: Int): this() {
i nit { class:
// do stuff sealed - only subclass in same file
}
inside class:
val volume: I nt public - default. Everywhere.
get() { private - inside class, not subclasses
return w * h * l / 1000 protected - inside class and subclasses
}
internal - module
i nit {
// do stuff with volume
}
}
Inheritance Abstract classes
open class Aquarium ….. { abstract class AquariumFish {
open var water = volume * 0.9 abstract val color: String
}
open var volume
} class Shark: A quariumFish() {
override v al color = "gray"
class TowerTank (): Aquarium() { }
override var volume: Int class Plecostomus: AquariumFish() {
get() = (w * h * l / 1000 * override val color = "gold"
PI).toInt() }
set(value) {
h = (value * 1000) / (w * l)}
}
Interfaces Composition
interface FishAction { fun main (args: Array<String>) {
fun eat() delegate()
} }
class Shark: AquariumFish(), FishAction
{ fun delegate() {
override val color = "gray" val pleco = Plecostomus()
override fun eat() { println("Fish has has color
println("hunt and eat fish") ${pleco.color}")
} pleco.eat()
} }
fun feedFish(fish: FishAction) { interface FishAction {
// make some food then fun eat()
fish.eat() }
}
interface FishColor {
val color: String
}
Data Classes object GoldColor : FishColor {
override val color = "gold"
data class Decorations(val rocks: }
String, val wood: String, val diver:
String){ class PrintingFishAction(val food:
} String) : FishAction {
override fun eat() {
val d = Decorations("crystal", "wood", println(food)
"diver") }
val (rock, wood, diver) = d }
class Plecostomus (fishColor: F ishColor
dataClassInstance1.equals(dataClassInst = GoldColor):
ance2) FishAction by
val PrintingFishAction("eat a lot o f
dataClassInstance3.copy(dataClassInstan algae"),
ce2) FishColor by fishColor
Singleton / object enum
object Database enum class Color(val rgb: Int) {
RED(0xFF0000), GREEN(0x00FF00),
object MobyDickWhale { BLUE(0x0000FF);
val author = "Herman Melville" }
} Color.RED
Lesson 4
Pairs Lists
val equipment = "fishnet" to "catching val testList =
fish" listOf(11,12,13,14,15,16,17,18,19,20)
println(equipment.first) listOf<Int>(1,2,3,4,5,6,7,8,9,0).revers
println(equipment.second) ed()
val (tool, use) = fishnet var symptoms = mutableListOf("white
val fishnetString = fishnet.toString() spots", "red spots", "not eating",
println(fishnet.toList()) "bloated", "belly up")
symptoms.add("white fungus")
symptoms.remove("white fungus")
Nesting with parentheses: symptoms.contains("red")
val equip = ("fishnet" to "catching println(symptoms.subList(4,
fish") to ("of big size" to "and symptoms.size))
strong")
equipment.first.first listOf(1, 5, 3).sum()
listOf("a", "b", "cc").sumBy {
it.length }
Mapping Constants
val cures = h
ashMapOf("white spots" to const val C
ONSTANT = " top-level
"Ich", "red s ores" to "hole disease") constant" / / compile t ime
println(cures["white spots"]) object Constants {
const val CONSTANT2 = "object constant"
cures.getOrDefault("bloating", "sorry, }
I don't know")
class MyClass {
cures.getOrElse("bloating") {"No cure companion o bject {
for this"} const v al CONSTANT3 = "constant
in companion"
val inventory = mutableMapOf("fish net" }
to 1) }
inventory.put("tank scrubber", 3)
inventory.remove("fish net")
Extension functions Property extensions
fun String.hasSpaces(): Boolean { val AquariumPlant.isGreen: Boolean
val found = this.find { it == ' ' } get() = color == "green"
return found != null
} fun propertyExample() {
val plant = GreenLeafyPlant(30)
fun extensionExample() { plant.isGreen // true
“Does it have spaces?”.hasSpaces() }
}
⇒ f un S tring.hasSpaces() = find { it
== ' ' } != null
fun AquariumPlant.isRed() = color ==
"red"
fun AquariumPlant?.pull() {
this?.apply {
println("removing $this")
}
}
Generic classes Generics: Full example
open class WaterSupply(var
class MyList<T> { needsProcessed: Boolean)
fun get(pos: Int): T {
TODO("implement") class TapWater : WaterSupply(true) {
} fun addChemicalCleaners() {
fun addItem(item: T) {} needsProcessed = false
} }
}
fun workWithMyList() {
val intList: MyList<String> class FishStoreWater :
val fishList: MyList<Fish> WaterSupply(false)
}
class LakeWater : WaterSupply(true) {
fun filter() {
needsProcessed = false
}
}
class Aquarium<T>(val waterSupply: T)
fun genericsExample() {
val aquarium = Aquarium(TapWater())
aquarium.waterSupply.addChemicalCleanes
()
}
Generic constraint In and Out Types
Non-nullable: class Aquarium<out T: WaterSupply>(val
class Aquarium<T: Any>(val waterSupply: waterSupply: T) { …}
T)
interface Cleaner<in T: WaterSupply> {
class Aquarium<T: WaterSupply>(val fun clean(waterSupply: T)
waterSupply: T) }
Generic functions and methods Inline / reified
fun <T: WaterSupply> inline fun <reified R: W
aterSupply>
isWaterClean(aquarium: Aquarium<T>) { hasWaterSupplyOfType() = waterSupply is
println("aquarium water is clean: R
${aquarium.waterSupply.needsProcessed}"
) inline fun <reified T: W
aterSupply>
} WaterSupply.isOfType() = this is T
fun genericsFunExample() { inline fun <reified R: WaterSupply>
val aquarium = Aquarium(TapWater()) Aquarium<*>.hasWaterSupplyOfType() =
waterSupply is R
isWaterClean(aquarium)
}
fun <R: WaterSupply>
hasWaterSupplyOfType() = waterSupply is
R
Annotations Reflection
@file:JvmName(“InteropFish”) val classobj=Plant::class
@JvmStatic fun interop() for(m in
classobj.declaredMemberFunctions){
annotation class ImAPlant println(m.name)
@ImAPlant class Plant{...} }
lantObject = Plant::class
val p
for ( a in plantObject.annotations) {
println(a.annotationClass.simpleName)
}
Annotations for getters and setters Labeled breaks
@Target(PROPERTY_GETTER) fun labels() {
annotation class OnGet loop@ for (i in 1..100) {
@Target(PROPERTY_SETTER) for (j in 1..100) {
Annotation class OnSet if (i > 10) break@loop
}
@ImAPlant class Plant { }
@get:OnGet }
val isGrowing: Boolean = true
@ set:OnSet
v ar needsFood: boolean = false
}
Lesson 5
Lambda recap Higher order function
myFish.filter { fun myWith(name: String, block:
it.name.contains("i")}.joinToString (" String.() -> Unit) {
") { it.name } name.block()
}
Standard Library: apply & run Standard Library: with & repeat
fish.run { with(fish.name) {
name println(name)
} }
val f ish2 =
F ish().apply { repeat(3) { rep ->
name = “ sharky” println(" current repetition:
} $rep")}
Inline Lambda instead ofSAM
Inline fun myWith(name: S
tring, fun example() {
operation: String.() -> U nit) { runNow {
name.operation() println(“Passing a lambda as a
} Runnable”)
}