Kotlin

#14
TIOBE#23
PYPL#13
GitHub#19
RedMonk#14
IEEESpectrum#17
JetBrains#13
Programming LanguageObject-orientedFunctionalJVMAndroidServer-sideInterop

Programming Language

Kotlin

Overview

Kotlin is a programming language that runs on the JVM, developed by JetBrains.

Details

Kotlin is a programming language whose development began in 2011 by JetBrains and was officially released in 2016. It runs on the Java Virtual Machine (JVM) and offers 100% interoperability with Java while enabling more concise and safer code. It provides modern features such as null safety, type inference, extension functions, and data classes. In 2017, Google adopted it as an official development language for Android, and it is now recommended as "Kotlin First". It is utilized in a wide range of fields including server-side development, web development, and native app development.

Code Examples

Hello World

// Basic output
fun main() {
    println("Hello, World!")
    
    // Output using variables
    val message = "Hello, Kotlin!"
    println(message)
    
    // Output using string templates
    val name = "John"
    val age = 25
    println("My name is ${name} and I am ${age} years old.")
}

// Traditional function form
fun main(args: Array<String>) {
    println("Hello from main function!")
}

Variables and Types

fun main() {
    // Read-only variable (val)
    val name = "John" // Type inference
    val age: Int = 25 // Explicit type specification
    
    // Mutable variable (var)
    var score = 85
    score = 90 // Changeable
    
    // Basic types
    val height: Double = 175.5
    val isActive: Boolean = true
    val character: Char = 'K'
    
    // Nullable types
    val nullableName: String? = null
    val nonNullName: String = "Smith"
    
    // Safe call operator
    val length = nullableName?.length
    println("Nullable string length: $length")
    
    // Elvis operator
    val displayName = nullableName ?: "No name"
    println("Display name: $displayName")
    
    // Not-null assertion operator (!!)
    val definitelyNotNull = nonNullName!!
    println("Definitely not null: $definitelyNotNull")
    
    // String templates
    println("Name: $name, Age: $age, Height: ${height}cm")
    println("Active: ${if (isActive) "Yes" else "No"}")
}

Functions

// Basic function
fun add(a: Int, b: Int): Int {
    return a + b
}

// Expression function
fun multiply(a: Int, b: Int) = a * b

// Default arguments
fun greet(name: String, prefix: String = "Mr.") = "Hello, $prefix $name"

// Named arguments
fun createUser(name: String, age: Int, email: String = "") {
    println("User created: $name ($age years old) - $email")
}

// Variable arguments
fun sum(vararg numbers: Int): Int {
    return numbers.sum()
}

// Higher-order functions
fun calculate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
    return operation(a, b)
}

// Extension functions
fun String.isValidEmail(): Boolean {
    return this.contains("@") && this.contains(".")
}

fun main() {
    // Function calls
    println("5 + 3 = ${add(5, 3)}")
    println("4 × 6 = ${multiply(4, 6)}")
    
    // Default arguments
    println(greet("Smith"))
    println(greet("Johnson", "Dr."))
    
    // Named arguments
    createUser(name = "Wilson", age = 30, email = "[email protected]")
    createUser(age = 25, name = "Brown") // Can change order
    
    // Variable arguments
    println("Sum: ${sum(1, 2, 3, 4, 5)}")
    
    // Higher-order functions
    val result = calculate(10, 5) { x, y -> x - y }
    println("10 - 5 = $result")
    
    // Lambda expressions
    val numbers = listOf(1, 2, 3, 4, 5)
    val doubled = numbers.map { it * 2 }
    println("Doubled: $doubled")
    
    // Extension functions
    val email = "[email protected]"
    println("$email is valid email: ${email.isValidEmail()}")
}

Classes and Objects

// Basic class
class Person(val name: String, var age: Int) {
    // Properties
    val id: String = generateId()
    
    // Methods
    fun getInfo(): String = "$name ($age years old) - ID: $id"
    
    // Secondary constructor
    constructor(name: String) : this(name, 0)
    
    private fun generateId(): String = "ID_${name.hashCode()}"
}

// Data class
data class User(
    val id: Int,
    val name: String,
    val email: String
)

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

// Interface
interface Drawable {
    fun draw()
    
    // Default implementation
    fun info() = "This is a drawable object"
}

// Inheritance
abstract class Shape : Drawable {
    abstract val area: Double
    
    override fun info() = "This is a shape: area = $area"
}

class Circle(private val radius: Double) : Shape() {
    override val area: Double
        get() = Math.PI * radius * radius
    
    override fun draw() {
        println("Drawing a circle with radius $radius")
    }
}

// Object declaration (Singleton)
object DatabaseManager {
    fun connect(): String = "Connected to database"
    fun disconnect(): String = "Disconnected from database"
}

fun main() {
    // Class instantiation
    val person1 = Person("John Smith", 25)
    val person2 = Person("Jane Doe")
    
    println(person1.getInfo())
    println(person2.getInfo())
    
    // Data class
    val user = User(1, "Wilson", "[email protected]")
    println("User: $user")
    
    // Data class copy
    val updatedUser = user.copy(email = "[email protected]")
    println("Updated user: $updatedUser")
    
    // Destructuring declaration
    val (id, name, email) = user
    println("ID: $id, Name: $name, Email: $email")
    
    // Sealed class
    val results = listOf(
        Result.Success("Data retrieved"),
        Result.Error("Network error"),
        Result.Loading
    )
    
    results.forEach { result ->
        when (result) {
            is Result.Success -> println("Success: ${result.data}")
            is Result.Error -> println("Error: ${result.message}")
            is Result.Loading -> println("Loading...")
        }
    }
    
    // Inheritance and polymorphism
    val circle = Circle(5.0)
    circle.draw()
    println(circle.info())
    
    // Object declaration
    println(DatabaseManager.connect())
    println(DatabaseManager.disconnect())
}

Collections and Functional Programming

fun main() {
    // Lists
    val numbers = listOf(1, 2, 3, 4, 5)
    val mutableNumbers = mutableListOf(1, 2, 3)
    mutableNumbers.add(4)
    
    // Sets
    val uniqueNumbers = setOf(1, 2, 2, 3, 3)
    println("Unique numbers: $uniqueNumbers")
    
    // Maps
    val ages = mapOf("Smith" to 25, "Johnson" to 30, "Wilson" to 28)
    val mutableAges = mutableMapOf<String, Int>()
    mutableAges["Brown"] = 35
    
    // Functional methods
    val evenNumbers = numbers.filter { it % 2 == 0 }
    println("Even numbers: $evenNumbers")
    
    val doubled = numbers.map { it * 2 }
    println("Doubled: $doubled")
    
    val sum = numbers.reduce { acc, n -> acc + n }
    println("Sum: $sum")
    
    val sumWithInitial = numbers.fold(10) { acc, n -> acc + n }
    println("Sum with initial: $sumWithInitial")
    
    // Grouping
    val words = listOf("apple", "banana", "apricot", "cherry", "avocado")
    val groupedByFirstLetter = words.groupBy { it.first() }
    println("Grouped by first letter: $groupedByFirstLetter")
    
    // Method chaining
    val result = words
        .filter { it.startsWith("a") }
        .map { it.uppercase() }
        .sorted()
    println("Processing result: $result")
    
    // Sequences (lazy evaluation)
    val largeNumbers = generateSequence(1) { it + 1 }
        .filter { it % 2 == 0 }
        .take(5)
        .toList()
    println("Sequence result: $largeNumbers")
}

Scope Functions

data class Person(var name: String, var age: Int)

fun main() {
    // let - Object transformation and null safety
    val person: Person? = Person("Smith", 25)
    person?.let {
        println("${it.name} is ${it.age} years old")
    }
    
    val length = "Hello, Kotlin"?.let {
        println("String: $it")
        it.length // Return value
    }
    println("String length: $length")
    
    // run - Object configuration and result computation
    val message = Person("Johnson", 30).run {
        age += 1
        "Next year $name will be $age years old"
    }
    println(message)
    
    // with - Consecutive method calls on object
    val numbers = mutableListOf<Int>()
    with(numbers) {
        add(1)
        add(2)
        add(3)
        println("List: $this")
    }
    
    // apply - Object configuration
    val person2 = Person("", 0).apply {
        name = "Wilson"
        age = 28
    }
    println("After setup: $person2")
    
    // also - Additional processing
    val person3 = Person("Brown", 35).also {
        println("Created person: ${it.name}")
    }
    
    // takeIf/takeUnless - Conditional processing
    val adult = person3.takeIf { it.age >= 18 }
    println("Adult: $adult")
    
    val notTeenager = person3.takeUnless { it.age in 13..19 }
    println("Not teenager: $notTeenager")
}

Exception Handling

// Custom exception class
class ValidationException(message: String) : Exception(message)

fun validateAge(age: Int) {
    if (age < 0) {
        throw ValidationException("Age must be 0 or greater")
    }
    if (age > 150) {
        throw ValidationException("Age must be 150 or less")
    }
}

fun divide(a: Int, b: Int): Double {
    if (b == 0) {
        throw ArithmeticException("Cannot divide by zero")
    }
    return a.toDouble() / b
}

fun main() {
    // try-catch statement
    try {
        val result = divide(10, 2)
        println("10 ÷ 2 = $result")
    } catch (e: ArithmeticException) {
        println("Arithmetic error: ${e.message}")
    }
    
    // Multiple exception catching
    try {
        validateAge(-5)
    } catch (e: ValidationException) {
        println("Validation error: ${e.message}")
    } catch (e: Exception) {
        println("Unexpected error: ${e.message}")
    } finally {
        println("Cleanup processing")
    }
    
    // try expression (returns value)
    val safeDivision = try {
        divide(10, 0)
    } catch (e: ArithmeticException) {
        0.0 // Default value
    }
    println("Safe division result: $safeDivision")
    
    // runCatching (functional approach)
    val result = runCatching {
        divide(15, 3)
    }
    
    result
        .onSuccess { println("Success: $it") }
        .onFailure { println("Failure: ${it.message}") }
    
    // getOrElse
    val safeResult = runCatching { divide(10, 0) }
        .getOrElse { -1.0 }
    println("Result with default: $safeResult")
    
    // fold
    val foldResult = runCatching { validateAge(25) }
        .fold(
            onSuccess = { "Age validation successful" },
            onFailure = { "Age validation failed: ${it.message}" }
        )
    println(foldResult)
}

Coroutines (Cooperative Concurrency)

import kotlinx.coroutines.*

// suspend function
suspend fun fetchUserData(userId: Int): String {
    delay(1000) // Asynchronous wait (1 second)
    return "User $userId data"
}

suspend fun fetchUserPosts(userId: Int): List<String> {
    delay(800) // Asynchronous wait (0.8 seconds)
    return listOf("Post 1", "Post 2", "Post 3")
}

fun main() = runBlocking {
    println("=== Basic Coroutine ===")
    
    // Basic launch
    val job = launch {
        repeat(3) {
            println("Coroutine running: $it")
            delay(500)
        }
    }
    
    delay(1000)
    job.cancel()
    println("Job cancelled")
    
    println("\n=== async/await ===")
    
    // Concurrent processing with async/await
    val userData = async { fetchUserData(1) }
    val userPosts = async { fetchUserPosts(1) }
    
    println("User data: ${userData.await()}")
    println("User posts: ${userPosts.await()}")
    
    println("\n=== Error Handling ===")
    
    // Error handling
    try {
        val errorJob = async {
            delay(100)
            throw Exception("Something went wrong")
        }
        errorJob.await()
    } catch (e: Exception) {
        println("Caught error: ${e.message}")
    }
    
    println("\n=== CoroutineScope ===")
    
    // Custom scope
    val customScope = CoroutineScope(Dispatchers.Default + Job())
    
    customScope.launch {
        println("Running in custom scope")
        delay(100)
        println("Custom scope completed")
    }
    
    delay(200) // Wait for completion
    customScope.cancel() // Cancel scope
    
    println("Program finished")
}

Versions

Version Release Date Major Features
Kotlin 2.1 2024-11 Kotlin Multiplatform improvements, New K2 compiler
Kotlin 2.0 2024-05 K2 compiler stable, Kotlin Multiplatform stable
Kotlin 1.9 2023-07 Enum entries function, Data object declarations
Kotlin 1.8 2023-02 Recursive generic types, @JvmMultifileClass improvements
Kotlin 1.7 2022-06 Kotlin Multiplatform Mobile Alpha, Builder inference
Kotlin 1.6 2021-11 Stable exhaustive when, Kover code coverage
Kotlin 1.5 2021-05 JVM IR backend stable, Value classes

Reference Links

Official Documentation

Learning Resources

Development Tools