Kotlin Programming
This guide provides an introduction to Kotlin, a modern, statically typed programming language developed by JetBrains. Kotlin is widely used for Android development, server-side applications, and multiplatform projects. It is designed to be fully interoperable with Java while offering a more concise and safer syntax.
1. Environment Setup
To start writing Kotlin code, you have a few options:
- IntelliJ IDEA: The recommended Integrated Development Environment (IDE) for Kotlin, developed by JetBrains. The Community Edition is free.
- Android Studio: The official IDE for Android development, which includes built-in support for Kotlin.
- Kotlin Playground: A web-based compiler useful for testing quick snippets without installation (play.kotl.in).
2. Variables and Basic Data Types
Kotlin distinguishes between mutable (changeable) and immutable (read-only) variables.
Variables: val vs var
val(Value): Read-only variable. Once assigned, its value cannot be changed (equivalent tofinalin Java).var(Variable): Mutable variable. Its value can be reassigned.
val pi = 3.14159 // Cannot be reassigned
var score = 0 // Can be reassigned
score = 10
Type Inference
Kotlin is statically typed, but you do not always have to declare the type explicitly. The compiler can infer the type from the context.
val message: String = "Hello, Kotlin" // Explicit type
val count = 42 // Infered as Int
Basic Types
- Numbers:
Byte,Short,Int,Long,Float,Double - Characters & Strings:
Char,String - Booleans:
Boolean(eithertrueorfalse)
String Templates
You can insert variables or expressions directly into strings using the $ symbol.
val name = "Alice"
val age = 25
println("My name is $name and I am $age years old.")
println("Next year, I will be ${age + 1} years old.")
3. Control Flow
If-Else as an Expression
In Kotlin, if is an expression, meaning it can return a value. This often eliminates the need for a ternary operator.
val a = 10
val b = 20
val max = if (a > b) {
a
} else {
b
}
The when Expression
when replaces the traditional switch statement found in other languages. It matches its argument against all branches sequentially until some branch condition is satisfied.
val trafficLight = "Yellow"
val action = when (trafficLight) {
"Red" -> "Stop"
"Yellow" -> "Slow down"
"Green" -> "Go"
else -> "Unknown signal"
}
Loops
Kotlin supports standard while and do-while loops, as well as a flexible for loop that uses ranges.
// Loop from 1 to 5 (inclusive)
for (i in 1..5) {
println(i)
}
// Loop downward with a specific step
for (i in 6 downTo 0 step 2) {
println(i) // Prints 6, 4, 2, 0
}
// Iterating over a list
val fruits = listOf("Apple", "Banana", "Cherry")
for (fruit in fruits) {
println(fruit)
}
4. Functions
Functions in Kotlin are declared using the fun keyword.
Standard Function Declaration
fun add(x: Int, y: Int): Int {
return x + y
}
Single-Expression Functions
If a function returns a single expression, you can omit the curly braces and the return keyword.
fun multiply(x: Int, y: Int): Int = x * y
Default and Named Arguments
You can assign default values to parameters. When calling the function, you can choose to omit those arguments or use named arguments for clarity.
fun greet(name: String, prefix: String = "Hello") {
println("$prefix, $name")
}
fun main() {
greet("Alice") // Prints: Hello, Alice
greet("Bob", "Good morning") // Prints: Good morning, Bob
greet(prefix = "Welcome", name = "Charlie") // Using named arguments
}
5. Null Safety
One of Kotlin's primary design goals is to reduce the occurrence of NullPointerException (NPE). Kotlin distinguishes between nullable and non-nullable types.
Nullable vs. Non-Nullable
By default, variables cannot hold null. To allow a variable to hold null, you must append a ? to the type.
var nonNullableName: String = "John"
// nonNullableName = null // Compiler error
var nullableName: String? = "John"
nullableName = null // Allowed
Safe Call Operator (?.)
To safely access a property or call a method on a nullable object, use the ?. operator. If the object is null, the expression returns null instead of throwing an exception.
val length: Int? = nullableName?.length
Elvis Operator (?:)
The Elvis operator allows you to provide a default value when an expression evaluates to null.
val nameLength = nullableName?.length ?: 0 // If nullableName is null, uses 0
Not-Null Assertion Operator (!!)
If you are certain that a nullable variable is not null, you can force it using !!. However, if the value is null, this will throw a NullPointerException.
val lengthForced = nullableName!!.length // Use with caution
6. Classes and Object-Oriented Programming
Class Definition and Constructors
Classes are declared using the class keyword. Kotlin uses a primary constructor defined in the class header.
class Person(val name: String, var age: Int) {
// Optional initializer block
init {
println("A Person instance for $name has been created.")
}
}
fun main() {
val person = Person("Alice", 30)
println(person.name) // Accessing properties
}
Inheritance
By default, Kotlin classes are closed (final) and cannot be inherited. To make a class inheritable, mark it with the open keyword.
open class Vehicle(val speed: Int) {
open fun drive() {
println("Driving at $speed km/h")
}
}
class Car(speed: Int, val gearCount: Int) : Vehicle(speed) {
override fun drive() {
println("Driving a car at $speed km/h with $gearCount gears")
}
}
Data Classes
Data classes are designed to hold data. The compiler automatically generates utility methods such as toString(), equals(), hashCode(), and copy() from the properties declared in the primary constructor.
data class User(val id: Int, val name: String)
fun main() {
val user1 = User(1, "Bob")
val user2 = user1.copy(name = "Robert") // Copies the object with modified property
println(user1) // Prints: User(id=1, name=Bob)
}
Interfaces
Interfaces in Kotlin can contain declarations of abstract methods, as well as method implementations.
interface Drivable {
fun accelerate()
fun stop() {
println("Vehicle stopped") // Default implementation
}
}
class Bicycle : Drivable {
override fun accelerate() {
println("Pedaling faster")
}
}
7. Collections
Kotlin provides standard collection types divided into read-only and mutable versions.
Lists
// Read-only list
val readOnlyList = listOf("Red", "Green", "Blue")
// Mutable list
val mutableList = mutableListOf("Red", "Green")
mutableList.add("Blue")
Sets
Sets contain unique elements.
val numberSet = setOf(1, 2, 3, 3) // Contains: 1, 2, 3
Maps
Maps contain key-value pairs.
val capitals = mapOf("USA" to "Washington", "France" to "Paris")
println(capitals["USA"])
Collection Operations
Kotlin offers a functional API for manipulating collections.
val numbers = listOf(1, 2, 3, 4, 5, 6)
val evenNumbers = numbers.filter { it % 2 == 0 } // [2, 4, 6]
val doubled = numbers.map { it * 2 } // [2, 4, 6, 8, 10, 12]
8. Extension Functions
Extension functions allow you to add new functions to existing classes without modifying their source code or inheriting from them.
// Extending the String class
fun String.removeFirstAndLast(): String {
if (this.length <= 2) return ""
return this.substring(1, this.length - 1)
}
fun main() {
val text = "Kotlin"
println(text.removeFirstAndLast()) // Prints: otli
}
9. Basic Coroutines Overview
Coroutines are used for writing asynchronous, non-blocking code. To use coroutines, you typically add the kotlinx-coroutines-core dependency to your project build files.
Key Concepts
suspendfunctions: Functions marked withsuspendcan be paused and resumed without blocking the current thread.- Coroutine Builders:
launchstarts a new coroutine without returning a result, whileasyncreturns aDeferredvalue that can be awaited.
import kotlinx.coroutines.*
suspend fun fetchData(): String {
delay(1000) // Simulates a network delay without blocking the thread
return "Data retrieved"
}
fun main() = runBlocking {
println("Start")
val result = fetchData()
println(result)
println("End")
}
In the example above, runBlocking acts as an adapter that starts a coroutine and blocks the main thread until all coroutines inside it complete, which is useful for main functions and unit tests.
The guide was created in June 2026.