DEV Community

Dev Cookies
Dev Cookies

Posted on

1

Ultimate Kotlin Cheatsheet

Table of Contents

Basics

Hello World

fun main() {
    println("Hello, World!")
}
Enter fullscreen mode Exit fullscreen mode

Comments

// Single-line comment

/*
   Multi-line
   comment
*/

/**
 * KDoc comment
 * @param args command line arguments
 */
Enter fullscreen mode Exit fullscreen mode

Variables & Data Types

Variable Declaration

val immutable: String = "Cannot be changed" // Read-only (immutable)
var mutable: String = "Can be changed"      // Mutable
mutable = "New value"

// Type inference
val inferred = "Type is inferred as String"
Enter fullscreen mode Exit fullscreen mode

Basic Types

// Numbers
val byte: Byte = 127                // 8 bits
val short: Short = 32767            // 16 bits
val int: Int = 2147483647           // 32 bits
val long: Long = 9223372036854775807L // 64 bits
val float: Float = 3.14f            // 32 bits
val double: Double = 3.14159        // 64 bits

// Characters and strings
val char: Char = 'A'
val string: String = "Hello"
val multiline: String = """
    This is a
    multiline string
    No escaping needed
"""

// Boolean
val boolean: Boolean = true

// Type conversion
val longFromInt: Long = int.toLong()
Enter fullscreen mode Exit fullscreen mode

String Templates

val name = "Kotlin"
println("Hello, $name!")              // Simple variable
println("Array size: ${array.size}")  // Expression
Enter fullscreen mode Exit fullscreen mode

Control Flow

Conditionals

// If expression (returns a value)
val max = if (a > b) a else b

// If statement
if (x > 0) {
    println("Positive")
} else if (x < 0) {
    println("Negative")
} else {
    println("Zero")
}

// When expression (enhanced switch)
when (x) {
    1 -> println("One")
    2, 3 -> println("Two or Three")
    in 4..10 -> println("Between 4 and 10")
    !in 20..30 -> println("Not between 20 and 30")
    is String -> println("Is a String of length ${x.length}")
    else -> println("Otherwise")
}

// When as an expression
val result = when (x) {
    0, 1 -> "Binary digit"
    else -> "Not a binary digit"
}
Enter fullscreen mode Exit fullscreen mode

Loops

// For loop with range
for (i in 1..5) {
    println(i) // 1, 2, 3, 4, 5
}

// For loop with step
for (i in 1..10 step 2) {
    println(i) // 1, 3, 5, 7, 9
}

// For loop downward
for (i in 5 downTo 1) {
    println(i) // 5, 4, 3, 2, 1
}

// For loop with indices
for (i in array.indices) {
    println(array[i])
}

// For loop with index
for ((index, value) in array.withIndex()) {
    println("Element at $index is $value")
}

// While loop
while (condition) {
    // code
}

// Do-while loop
do {
    // code
} while (condition)
Enter fullscreen mode Exit fullscreen mode

Loop Control

// Break
for (i in 1..10) {
    if (i == 5) break
    println(i) // 1, 2, 3, 4
}

// Continue
for (i in 1..10) {
    if (i % 2 == 0) continue
    println(i) // 1, 3, 5, 7, 9
}

// Labeled break/continue
outer@ for (i in 1..10) {
    for (j in 1..10) {
        if (i * j > 50) break@outer
    }
}
Enter fullscreen mode Exit fullscreen mode

Functions

Basic Function

fun greet(name: String): String {
    return "Hello, $name!"
}

// Single-expression function
fun greet(name: String): String = "Hello, $name!"

// Type inference for return value
fun greet(name: String) = "Hello, $name!"
Enter fullscreen mode Exit fullscreen mode

Parameters

// Default parameters
fun greet(name: String, greeting: String = "Hello") = "$greeting, $name!"

// Named arguments
greet(greeting = "Hi", name = "Kotlin")

// Variable number of arguments (varargs)
fun sum(vararg numbers: Int): Int {
    return numbers.sum()
}
sum(1, 2, 3, 4) // 10

// Spread operator for varargs
val numbers = intArrayOf(1, 2, 3)
sum(*numbers)
Enter fullscreen mode Exit fullscreen mode

Local Functions

fun outer() {
    fun inner() {
        // Has access to outer's scope
    }
    inner()
}
Enter fullscreen mode Exit fullscreen mode

Infix Functions

infix fun Int.plus(other: Int): Int = this + other
val result = 1 plus 2 // Same as 1.plus(2)
Enter fullscreen mode Exit fullscreen mode

Operator Overloading

operator fun Point.plus(other: Point): Point {
    return Point(x + other.x, y + other.y)
}
val result = point1 + point2 // Calls point1.plus(point2)
Enter fullscreen mode Exit fullscreen mode

Higher-Order Functions

// Function that takes a function as parameter
fun operation(x: Int, y: Int, op: (Int, Int) -> Int): Int {
    return op(x, y)
}

// Calling with lambda
operation(1, 2) { a, b -> a + b }

// Function that returns a function
fun multiplier(factor: Int): (Int) -> Int {
    return { it * factor }
}
val double = multiplier(2)
double(5) // 10
Enter fullscreen mode Exit fullscreen mode

Collections

Creating Collections

// Immutable collections (preferred)
val list = listOf(1, 2, 3)             // List<Int>
val set = setOf("apple", "banana")     // Set<String>
val map = mapOf("a" to 1, "b" to 2)    // Map<String, Int>

// Mutable collections
val mutableList = mutableListOf(1, 2, 3)
val mutableSet = mutableSetOf("apple", "banana")
val mutableMap = mutableMapOf("a" to 1, "b" to 2)

// Empty collections
val emptyList = emptyList<String>()
val emptySet = emptySet<Int>()
val emptyMap = emptyMap<String, Int>()

// Array
val array = arrayOf(1, 2, 3)
val intArray = intArrayOf(1, 2, 3)     // Primitive int[]
Enter fullscreen mode Exit fullscreen mode

Collection Operations

// Element access
list[0]                  // First element
list.first()             // First element
list.last()              // Last element
map["a"]                 // Value for key "a"

// Adding elements (mutable collections)
mutableList.add(4)
mutableSet.add("cherry")
mutableMap["c"] = 3

// Removing elements (mutable collections)
mutableList.remove(2)
mutableSet.remove("apple")
mutableMap.remove("a")

// Collection transformations
val doubled = list.map { it * 2 }            // [2, 4, 6]
val even = list.filter { it % 2 == 0 }       // [2]
val sum = list.reduce { acc, i -> acc + i }  // 6
val grouped = list.groupBy { it % 2 }        // {1=[1, 3], 0=[2]}
val flattened = listOf(listOf(1), listOf(2, 3)).flatten() // [1, 2, 3]

// Checking elements
list.contains(2)         // true
2 in list                // true
list.any { it > 2 }      // true
list.all { it < 10 }     // true
list.none { it < 0 }     // true
list.count { it % 2 == 0 } // 1

// Collection information
list.size                // 3
list.isEmpty()           // false
list.isNotEmpty()        // true

// Finding elements
list.find { it > 2 }     // 3
list.findLast { it < 3 } // 2
list.indexOf(2)          // 1

// Sorting
list.sorted()            // Natural order
list.sortedDescending()  // Reverse natural order
list.sortedBy { it % 2 } // Custom order
Enter fullscreen mode Exit fullscreen mode

Classes & Objects

Class Declaration

class Person {
    var name: String = ""
    var age: Int = 0

    fun introduce() {
        println("I'm $name, $age years old")
    }
}

// Instantiation
val person = Person()
person.name = "John"
person.age = 25
person.introduce()
Enter fullscreen mode Exit fullscreen mode

Constructors

// Primary constructor
class Person(val name: String, var age: Int) {
    // Init blocks run in sequence with property initializers
    init {
        require(age >= 0) { "Age cannot be negative" }
    }
}

// Secondary constructor
class Person {
    val name: String
    var age: Int

    constructor(name: String, age: Int) {
        this.name = name
        this.age = age
    }

    constructor(name: String) : this(name, 0)
}
Enter fullscreen mode Exit fullscreen mode

Properties

class Person {
    // Backing field auto-generated
    var name: String = ""
        get() = field.uppercase()
        set(value) {
            field = value.trim()
        }

    // Custom getter (read-only property)
    val isAdult: Boolean
        get() = age >= 18

    // Late-initialized property (no initial value needed)
    lateinit var job: String

    // Lazy property - initialized on first access
    val socialSecurityNumber: String by lazy {
        calculateSSN() // Expensive operation
    }
}
Enter fullscreen mode Exit fullscreen mode

Data Classes

// Automatically implements equals(), hashCode(), toString(), copy()
data class User(val name: String, val age: Int)

val user1 = User("John", 25)
val user2 = user1.copy(age = 26)
val (name, age) = user1 // Destructuring declaration
Enter fullscreen mode Exit fullscreen mode

Inheritance

// All classes are final by default
open class Animal(val name: String) {
    open fun makeSound() {
        println("Some sound")
    }
}

class Dog(name: String) : Animal(name) {
    override fun makeSound() {
        println("Woof!")
    }
}
Enter fullscreen mode Exit fullscreen mode

Abstract Classes

abstract class Shape {
    abstract val area: Double
    abstract fun draw()

    // Non-abstract function
    fun display() {
        println("Displaying shape with area: $area")
    }
}

class Circle(val radius: Double) : Shape() {
    override val area: Double
        get() = Math.PI * radius * radius

    override fun draw() {
        println("Drawing a circle")
    }
}
Enter fullscreen mode Exit fullscreen mode

Interfaces

interface Clickable {
    // Abstract property
    val clickCount: Int

    // Abstract method
    fun onClick()

    // Method with default implementation
    fun showOff() {
        println("I'm clickable!")
    }
}

interface Focusable {
    fun showOff() {
        println("I'm focusable!")
    }
}

// Multiple interface implementation
class Button : Clickable, Focusable {
    override val clickCount: Int = 0

    override fun onClick() {
        println("Button clicked")
    }

    // Must override conflicting method
    override fun showOff() {
        super<Clickable>.showOff()
        super<Focusable>.showOff()
    }
}
Enter fullscreen mode Exit fullscreen mode

Singleton (Object)

object Singleton {
    val property = "I'm a singleton"
    fun method() = "Only one instance exists"
}

// Usage
Singleton.property
Singleton.method()
Enter fullscreen mode Exit fullscreen mode

Companion Object

class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}

// Usage (like static methods in Java)
val instance = MyClass.create()
Enter fullscreen mode Exit fullscreen mode

Enum Classes

enum class Direction {
    NORTH, EAST, SOUTH, WEST
}

// Enum with properties and methods
enum class Color(val rgb: Int) {
    RED(0xFF0000),
    GREEN(0x00FF00),
    BLUE(0x0000FF);

    fun containsRed(): Boolean = (rgb and 0xFF0000 != 0)
}
Enter fullscreen mode Exit fullscreen mode

Sealed Classes

// Restricted class hierarchy
sealed class Result {
    class Success(val data: Any) : Result()
    class Error(val message: String) : Result()
    object Loading : Result()
}

// Ideal for use with when
fun handleResult(result: Result) = when (result) {
    is Result.Success -> println("Success: ${result.data}")
    is Result.Error -> println("Error: ${result.message}")
    is Result.Loading -> println("Loading...")
    // No else branch needed as all subclasses are covered
}
Enter fullscreen mode Exit fullscreen mode

Type Aliases

typealias ClickHandler = (Button, ClickEvent) -> Unit
typealias StringMap = Map<String, String>
Enter fullscreen mode Exit fullscreen mode

Null Safety

Nullable Types

// Non-nullable type
var nonNull: String = "value"
nonNull = null // Compilation error

// Nullable type
var nullable: String? = "value"
nullable = null // OK
Enter fullscreen mode Exit fullscreen mode

Safe Calls

// Returns null if user is null
val length = user?.name?.length

// Chain of safe calls
val city = user?.address?.city

// Safe call with let
user?.let {
    println("User name is ${it.name}")
}
Enter fullscreen mode Exit fullscreen mode

Elvis Operator

// Default value if null
val length = str?.length ?: 0

// Throw exception if null
val name = user?.name ?: throw IllegalArgumentException("User must have a name")
Enter fullscreen mode Exit fullscreen mode

Not-null Assertion

// Throws NullPointerException if null
val length = str!!.length
Enter fullscreen mode Exit fullscreen mode

Safe Casts

// Returns null if cast fails
val str: String? = value as? String
Enter fullscreen mode Exit fullscreen mode

Platform Types

// Types coming from Java are treated as platform types (neither nullable nor non-null)
// import java.util.Date
// fun getDate(): Date = Date() // Java method
// val date: Date = getDate() // Treated as non-nullable
// val nullableDate: Date? = getDate() // Treated as nullable
Enter fullscreen mode Exit fullscreen mode

Coroutines

Basic Coroutine

import kotlinx.coroutines.*

fun main() = runBlocking {
    launch {
        delay(1000)
        println("World!")
    }
    println("Hello,")
}
// Prints: Hello, (waits 1 second) World!
Enter fullscreen mode Exit fullscreen mode

Coroutine Builders

// launch - fire and forget
launch {
    // Coroutine code
}

// async - returns a result
val deferred = async {
    // Coroutine code that returns a value
    "Result"
}
val result = deferred.await()

// runBlocking - bridges blocking and non-blocking worlds
runBlocking {
    // Coroutine code
}

// coroutineScope - creates a new scope and waits for all children
coroutineScope {
    launch { delay(1000) }
    launch { delay(2000) }
} // Waits for both launches to complete
Enter fullscreen mode Exit fullscreen mode

Coroutine Context & Dispatchers

// Dispatchers
launch(Dispatchers.Default) { /* CPU-intensive work */ }
launch(Dispatchers.IO) { /* I/O operations */ }
launch(Dispatchers.Main) { /* UI updates */ }

// Named coroutines for debugging
launch(CoroutineName("my-coroutine")) { /* ... */ }

// Combined context
launch(Dispatchers.IO + CoroutineName("io-work")) { /* ... */ }

// Job for cancellation control
val job = launch { /* ... */ }
job.cancel()
job.join() // Wait for completion
Enter fullscreen mode Exit fullscreen mode

Exception Handling

val handler = CoroutineExceptionHandler { _, exception ->
    println("Caught $exception")
}

val job = GlobalScope.launch(handler) {
    throw RuntimeException("Oops")
}

// supervisorScope for independent failure of children
supervisorScope {
    val job1 = launch { /* may fail */ }
    val job2 = launch { /* continues even if job1 fails */ }
}
Enter fullscreen mode Exit fullscreen mode

Flow

// Creating a flow
val flow = flow {
    for (i in 1..3) {
        delay(100)
        emit(i)
    }
}

// Collecting a flow
flow.collect { value ->
    println(value)
}

// Flow operators
flow.map { it * 2 }
    .filter { it > 0 }
    .take(2)
    .collect { println(it) }
Enter fullscreen mode Exit fullscreen mode

Extension Functions

Basic Extension Function

// Add a method to String class
fun String.addExclamation(): String {
    return this + "!"
}

// Usage
val excited = "Hello".addExclamation() // "Hello!"
Enter fullscreen mode Exit fullscreen mode

Extension Properties

val String.lastChar: Char
    get() = this[length - 1]

// Usage
val last = "Kotlin".lastChar // 'n'
Enter fullscreen mode Exit fullscreen mode

Nullable Receiver

fun String?.isNullOrBlank(): Boolean {
    return this == null || this.isBlank()
}

// Usage
val result = null.isNullOrBlank() // true
Enter fullscreen mode Exit fullscreen mode

Companion Object Extensions

class MyClass {
    companion object {}
}

fun MyClass.Companion.create(): MyClass = MyClass()

// Usage
val instance = MyClass.create()
Enter fullscreen mode Exit fullscreen mode

Functional Programming

Lambda Expressions

// Full syntax
val sum = { a: Int, b: Int -> a + b }

// Type inference
val multiply: (Int, Int) -> Int = { a, b -> a * b }

// Calling a lambda
sum(1, 2) // 3

// Lambda with receiver
val greet: String.() -> String = { "Hello, $this!" }
"Kotlin".greet() // "Hello, Kotlin!"
Enter fullscreen mode Exit fullscreen mode

Function References

// Reference to a function
fun isOdd(x: Int) = x % 2 != 0
val numbers = listOf(1, 2, 3)
numbers.filter(::isOdd) // [1, 3]

// Reference to a constructor
class Person(val name: String)
val createPerson = ::Person
val person = createPerson("John")

// Reference to an instance method
val predicate = String::isNotEmpty
Enter fullscreen mode Exit fullscreen mode

Higher-Order Functions

// Standard library examples
val numbers = listOf(1, 2, 3, 4)
numbers.filter { it % 2 == 0 }      // [2, 4]
numbers.map { it * it }             // [1, 4, 9, 16]
numbers.forEach { println(it) }     // Prints each number
numbers.fold(0) { acc, n -> acc + n } // 10
Enter fullscreen mode Exit fullscreen mode

Sequences

// Lazy evaluation (more efficient for chained operations)
val result = sequenceOf(1, 2, 3, 4)
    .filter { println("Filter: $it"); it % 2 == 0 }
    .map { println("Map: $it"); it * it }
    .first() // Only processes elements until first result

// Generate sequences
val fibonacci = sequence {
    var a = 0
    var b = 1
    while (true) {
        yield(a)
        val next = a + b
        a = b
        b = next
    }
}
fibonacci.take(5).toList() // [0, 1, 1, 2, 3]
Enter fullscreen mode Exit fullscreen mode

Scope Functions

// let - object as it, returns lambda result
val length = str?.let {
    println("Processing '$it'")
    it.length
}

// run - object as this, returns lambda result
val upperCase = str.run {
    println("Processing '$this'")
    uppercase()
}

// with - object as this, returns lambda result (extension-like)
val result = with(str) {
    println("Processing '$this'")
    length * 2
}

// apply - object as this, returns the object (builder-like)
val person = Person().apply {
    name = "John"
    age = 30
}

// also - object as it, returns the object (side effects)
val numbers = mutableListOf(1, 2, 3)
    .also { println("List: $it") }
    .also { it.add(4) }
Enter fullscreen mode Exit fullscreen mode

Learning Resources

Official Resources

Books

  • "Kotlin in Action" by Dmitry Jemerov and Svetlana Isakova
  • "Atomic Kotlin" by Bruce Eckel and Svetlana Isakova
  • "Programming Kotlin" by Venkat Subramaniam
  • "Head First Kotlin" by Dawn Griffiths and David Griffiths

Online Courses

Community

Blogs and Websites

Frameworks and Libraries

Practice Platforms

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

Image of Stellar post

How a Hackathon Win Led to My Startup Getting Funded

In this episode, you'll see:

  • The hackathon wins that sparked the journey.
  • The moment José and Joseph decided to go all-in.
  • Building a working prototype on Stellar.
  • Using the PassKeys feature of Soroban.
  • Getting funded via the Stellar Community Fund.

Watch the video 🎥

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay