Kotlin
#14
TIOBE#23
PYPL#13
GitHub#19
RedMonk#14
IEEESpectrum#17
JetBrains#13
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
- Kotlin Official Site - Official website
- Kotlin Documentation - Official documentation
- Kotlin Playground - Try Kotlin in browser
Learning Resources
- Kotlin Koans - Kotlin learning exercises
- Android Kotlin Fundamentals - Kotlin basics for Android development
- Kotlin for Java Developers - Kotlin for Java developers
Development Tools
- IntelliJ IDEA - Standard Kotlin IDE
- Android Studio - Android development environment
- Awesome Kotlin - Collection of Kotlin libraries and resources