1. Pengenalan Kotlin
Kotlin adalah bahasa pemrograman modern yang dikembangkan oleh JetBrains dan pertama kali dirilis pada tahun 2016. Pada tahun 2019, Google menjadikan Kotlin sebagai bahasa utama untuk pengembangan Android, menggantikan posisi Java.
Kotlin bisa berjalan di JVM (Java Virtual Machine), sehingga 100% interoperable dengan Java. Selain Android, Kotlin juga bisa digunakan untuk backend, web (Kotlin/JS), dan multiplatform (Kotlin Multiplatform).
Mengapa Memilih Kotlin?
| Keunggulan | Penjelasan |
|---|---|
| Sintaks Ringkas | Kode lebih sedikit 40% dibanding Java untuk hasil yang sama |
| Null Safety | Sistem tipe yang mencegah NullPointerException |
| Interoperable dengan Java | Bisa menggunakan semua library Java yang sudah ada |
| Android Official | Bahasa utama yang direkomendasikan Google untuk Android |
| Modern & Fungsional | Mendukung lambda, higher-order functions, extension functions |
| Coroutines | Async programming yang powerful dan mudah dipahami |
Kotlin vs Java
| Aspek | Kotlin | Java |
|---|---|---|
| Kode Boilerplate | π’ Sedikit | π΄ Banyak |
| Null Safety | π’ Built-in | π΄ Manual (hanya annotation) |
| Data Class | π’ Otomatis | π΄ Manual / IDE generate |
| Coroutines | π’ Native | π‘ Threads / CompletableFuture |
| Extension Function | π’ Ada | π΄ Tidak ada |
| Smart Cast | π’ Otomatis | π΄ Manual instanceof |
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β EKOSISTEM KOTLIN β β β β ββββββββββββ ββββββββββββ ββββββββββββββββββββ β β β Android β β Backend β β Multiplatform β β β β Jetpack β β Ktor β β KMP β β β β Compose β β Spring β β Shared Logic β β β β ViewModelβ β Micronautβ β iOS/Android/Web β β β ββββββββββββ ββββββββββββ ββββββββββββββββββββ β β β β ββββββββββββ ββββββββββββ ββββββββββββββββββββ β β β Web (JS) β β Desktop β β Scripting β β β β Kotlin/JSβ β Compose β β Kotlin Script β β β β React β β Desktop β β Gradle (KTS) β β β ββββββββββββ ββββββββββββ ββββββββββββββββββββ β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
2. Instalasi & Hello World
Ada beberapa cara untuk memulai belajar Kotlin:
Option 1: Kotlin Playground (Online)
# Cara paling mudah untuk mulai!
# Buka https://play.kotlinlang.org
# Langsung bisa menulis dan menjalankan kode Kotlin
# Tidak perlu instalasi apapun
# Contoh di Playground:
fun main() {
println("Halo, Kotlin!")
}
Option 2: IntelliJ IDEA
# 1. Download IntelliJ IDEA dari https://www.jetbrains.com/idea/ # (Community Edition β gratis) # 2. Instal dan buka IntelliJ IDEA # 3. File β New β Project β Kotlin β JVM # 4. Tambahkan file Main.kt # 5. Klik Run βΆοΈ # IntelliJ sudah include Kotlin plugin secara default
Menulis Program Kotlin Pertama
// File: Main.kt
fun main() {
println("Halo, dunia!")
println("Selamat datang di Kotlin!")
println("Nama saya: BeebaneLabs")
// Variabel
val nama = "Andi"
var umur = 25
println("Nama: $nama, Umur: $umur tahun")
}
// Output:
// Halo, dunia!
// Selamat datang di Kotlin!
// Nama saya: BeebaneLabs
// Nama: Andi, Umur: 25 tahun
Kotlin Script (CLI)
# Instal Kotlin di macOS dengan SDKMAN
curl -s "https://get.sdkman.io" | bash
sdk install kotlin
# Atau di Ubuntu
sudo snap install kotlin --classic
# Atau di Windows dengan scoop
scoop install kotlin
# Verifikasi
kotlin -version
# Output: kotlin version 1.9.x
# Kompilasi dan jalankan
kotlinc Main.kt -include-runtime -d Main.jar
java -jar Main.jar
# Atau gunakan Kotlin Script (.kts)
# File: hello.kts
# println("Hello from Kotlin Script!")
# kotlin hello.kts
Jika Anda belajar untuk Android, langsung gunakan Android Studio β IDE ini berbasis IntelliJ IDEA dan sudah include Kotlin, Gradle, dan Android SDK. Untuk non-Android, gunakan Kotlin Playground online atau IntelliJ IDEA Community Edition.
3. Variabel dan Tipe Data
Kotlin menggunakan val untuk konstanta (immutable) dan var untuk variabel (mutable). Type inference memungkinkan Anda tidak perlu selalu menulis tipe data secara eksplisit.
val vs var
fun main() {
// val = immutable (tidak bisa diubah nilainya) β PREFERRED
val nama: String = "Budi Santoso"
val umur: Int = 25
val tinggi: Double = 175.5
val is_active: Boolean = true
// var = mutable (bisa diubah nilainya)
var kota = "Jakarta" // Type inference β String
kota = "Surabaya" // β
Bisa diubah
// Type inference β Kotlin otomatis mendeteksi tipe
val angka = 42 // Int
val desimal = 3.14 // Double
val teks = "Hello" // String
val benar = true // Boolean
// String template / interpolation
println("Nama: $nama, Umur: $umur tahun")
// Nama: Budi Santoso, Umur: 25 tahun
// Expression dalam interpolation
println("2 + 3 = ${2 + 3}")
// 2 + 3 = 5
// Multiline string
val paragraf = """
Ini adalah paragraf
yang terdiri dari
beberapa baris.
""".trimIndent()
println(paragraf)
// Multiple assignment dengan destructuring
val (a, b, c) = Triple(1, 2, 3)
println("$a, $b, $c") // 1, 2, 3
// Type casting
val angkaStr = "42"
val angkaInt = angkaStr.toInt()
val angkaDouble = angkaStr.toDouble()
println(angkaInt) // 42
println(angkaDouble) // 42.0
}
Tipe Data Dasar
| Tipe | Contoh | Penjelasan |
|---|---|---|
Int | 42, -10, 0 | Bilangan bulat 32-bit |
Long | 42L | Bilangan bulat 64-bit |
Double | 3.14 | Bilangan desimal 64-bit |
Float | 3.14f | Bilangan desimal 32-bit |
String | "hello" | String / teks |
Boolean | true, false | Boolean / logika |
Char | 'A' | Satu karakter (single quotes) |
Array | arrayOf(1,2,3) | Array dengan tipe tetap |
4. Fungsi
Fungsi di Kotlin menggunakan keyword fun. Kotlin mendukung default parameters, named arguments, single-expression functions, dan variadic parameters.
// Fungsi dasar
fun sapa(nama: String): String {
return "Halo, $nama!"
}
// Single-expression function (disingkat)
fun sapaSingkat(nama: String) = "Halo, $nama!"
// Fungsi tanpa return value
fun cetakPesan(pesan: String) {
println(pesan)
}
// Default parameter
fun hitungLuas(panjang: Double = 1.0, lebar: Double = 1.0): Double {
return panjang * lebar
}
// Named arguments
fun buatProfil(nama: String, umur: Int, kota: String = "Jakarta") {
println("Nama: $nama, Umur: $umur, Kota: $kota")
}
fun main() {
println(sapa("Andi")) // Halo, Andi!
println(sapaSingkat("Budi")) // Halo, Budi!
// Default parameters
println(hitungLuas()) // 1.0
println(hitungLuas(5.0)) // 5.0
println(hitungLuas(5.0, 3.0)) // 15.0
// Named arguments β urutan bebas
buatProfil(umur = 25, nama = "Andi", kota = "Bandung")
// Nama: Andi, Umur: 25, Kota: Bandung
// Variadic parameter (vararg)
fun jumlahkan(vararg angka: Int): Int {
return angka.sum()
}
println(jumlahkan(1, 2, 3, 4)) // 10
// Lambda / Higher-order function
val kaliDua = { x: Int -> x * 2 }
println(kaliDua(5)) // 10
val angka = listOf(1, 2, 3, 4, 5)
val genap = angka.filter { it % 2 == 0 }
val kali3 = angka.map { it * 3 }
val total = angka.reduce { acc, i -> acc + i }
println(genap) // [2, 4]
println(kali3) // [3, 6, 9, 12, 15]
println(total) // 15
// Scope function β let, apply, with, also, run
val nama: String? = "Kotlin"
nama?.let {
println("Nama: $it") // Nama: Kotlin
}
data class User(var nama: String = "", var umur: Int = 0)
val user = User().apply {
nama = "Andi"
umur = 25
}
println(user) // User(nama=Andi, umur=25)
}
5. Kontrol Alur
Kotlin memiliki if/else, when (expression-based switch), for, while, dan do-while.
fun main() {
// If/Else β di Kotlin, if adalah EXPRESSION (bisa return nilai)
val umur = 20
val status = if (umur >= 18) "Dewasa" else "Remaja"
println(status) // Dewasa
// When β pengganti switch, sangat powerful
val hari = "Senin"
when (hari) {
"Senin" -> println("Hari Senin β awal minggu!")
"Selasa" -> println("Hari Selasa")
"Rabu" -> println("Hari Rabu")
"Kamis" -> println("Hari Kamis")
"Jumat" -> println("Hari Jumat β menjelang weekend!")
"Sabtu", "Minggu" -> println("Akhir pekan! π")
else -> println("Hari tidak valid")
}
// When sebagai expression
val nilai = 85
val grade = when {
nilai >= 90 -> "A"
nilai >= 80 -> "B"
nilai >= 70 -> "C"
nilai >= 60 -> "D"
else -> "E"
}
println("Grade: $grade") // Grade: B
// When dengan range
val skor = 75
when (skor) {
in 90..100 -> println("Sangat Baik")
in 80..89 -> println("Baik")
in 70..79 -> println("Cukup")
in 0..69 -> println("Perlu Perbaikan")
else -> println("Tidak valid")
}
// When dengan type check (smart cast)
fun cekTipe(obj: Any) {
when (obj) {
is String -> println("String dengan ${obj.length} karakter")
is Int -> println("Integer: $obj")
is Double -> println("Double: $obj")
else -> println("Tipe lain: ${obj::class.simpleName}")
}
}
cekTipe("Hello") // String dengan 5 karakter
cekTipe(42) // Integer: 42
}
Loops
fun main() {
// For loop dengan range
for (i in 1..5) {
print("$i ") // 1 2 3 4 5
}
println()
// Range eksklusif (sampai tapi tidak termasuk)
for (i in 0 until 5) {
print("$i ") // 0 1 2 3 4
}
println()
// Dengan step
for (i in 0..20 step 5) {
print("$i ") // 0 5 10 15 20
}
println()
// Countdown
for (i in 10 downTo 1) {
print("$i ") // 10 9 8 7 6 5 4 3 2 1
}
println()
// Iterasi collection
val buah = listOf("Apel", "Mangga", "Jeruk")
for (item in buah) {
println(item)
}
// Dengan index
for ((index, item) in buah.withIndex()) {
println("${index + 1}. $item")
}
// 1. Apel
// 2. Mangga
// 3. Jeruk
// ForEach extension
buah.forEach { item -> println(item) }
buah.forEachIndexed { index, item -> println("$index: $item") }
// While loop
var counter = 5
while (counter > 0) {
print("$counter ")
counter--
}
println() // 5 4 3 2 1
// do-while
var num = 1
do {
print("$num ")
num *= 2
} while (num <= 100)
println() // 1 2 4 8 16 32 64
// Break dan continue
for (i in 1..10) {
if (i == 3) continue // Skip 3
if (i == 7) break // Stop di 7
print("$i ")
}
println() // 1 2 4 5 6
}
6. Null Safety
Null Safety adalah salah satu fitur terbaik Kotlin. Secara default, tipe di Kotlin tidak bisa null. Jika ingin memperbolehkan null, harus ditandai secara eksplisit dengan ?.
fun main() {
// Tipe non-nullable (default)
var nama: String = "Andi"
// nama = null // β COMPILE ERROR!
// Tipe nullable β tambahkan ? setelah tipe
var alamat: String? = "Jakarta"
alamat = null // β
Boleh null
// ========== Safe Call Operator (?.) ==========
println(alamat?.length) // null (tidak crash!)
println(alamat?.uppercase()) // null
// ========== Elvis Operator (?:) ==========
// Default value jika null
val panjang = alamat?.length ?: 0
println(panjang) // 0
val kota = alamat ?: "Tidak Diketahui"
println(kota) // Tidak Diketahui
// ========== Not-Null Assertion (!!) ==========
// Memaksa unwrap β HATI-HATI bisa NullPointerException
var kotaNonNull: String? = "Bandung"
// println(kotaNonNull!!.length) // Aman: 7
kotaNonNull = null
// println(kotaNonNull!!.length) // β NullPointerException!
// ========== Safe Cast (as?) ==========
val obj: Any = "Hello"
val str: String? = obj as? String // Safe cast
val num: Int? = obj as? Int // null (bukan Int)
println(str) // Hello
println(num) // null
// ========== Let dengan Null Safety ==========
var input: String? = "Kotlin"
input?.let { value ->
println("Panjang: ${value.length}") // Panjang: 6
println("Uppercase: ${value.uppercase()}")
}
input = null
input?.let {
println("Ini tidak akan dieksekusi")
} ?: run {
println("Input adalah null") // Ini yang dieksekusi
}
// ========== Collections Nullable ==========
val list1: List<String> = listOf("A", "B") // Tidak bisa null, elemen tidak null
val list2: List<String?> = listOf("A", null, "B") // Elemen bisa null
val list3: List<String>? = null // List bisa null
// Filter null dari collection
val nonNull = list2.filterNotNull()
println(nonNull) // [A, B]
// ========== Contoh Praktis ==========
data class User(
val nama: String,
val email: String?,
val telepon: String?
)
fun tampilkanUser(user: User) {
println("Nama: ${user.nama}")
println("Email: ${user.email ?: "Tidak tersedia"}")
println("Telepon: ${user.telepon ?: "Tidak tersedia"}")
// Atau dengan let
user.email?.let {
println("Kirim email ke: $it")
}
}
val user1 = User("Andi", "andi@email.com", null)
tampilkanUser(user1)
// Nama: Andi
// Email: andi@email.com
// Telepon: Tidak tersedia
// Kirim email ke: andi@email.com
}
Operator !! memaksa unwrap nullable type β jika nilainya null, akan terjadi NullPointerException. Selalu gunakan ?.let atau ?: (elvis) sebagai alternatif yang lebih aman.
7. Collections
Kotlin memiliki collection API yang sangat lengkap dengan banyak fungsi bawaan β map, filter, reduce, sort, dan lainnya.
fun main() {
// ========== List ==========
// Immutable list
val buah = listOf("Apel", "Mangga", "Jeruk", "Pisang")
println(buah) // [Apel, Mangga, Jeruk, Pisang]
println(buah[0]) // Apel
println(buah.first()) // Apel
println(buah.last()) // Pisang
println(buah.size) // 4
// Mutable list
val buahMutable = mutableListOf("Apel", "Mangga")
buahMutable.add("Jeruk")
buahMutable.remove("Apel")
println(buahMutable) // [Mangga, Jeruk]
// ========== Set ==========
// Immutable set (unik, tidak berurutan)
val angkaSet = setOf(1, 2, 3, 2, 1)
println(angkaSet) // [1, 2, 3]
// Mutable set
val mutableSet = mutableSetOf("A", "B")
mutableSet.add("C")
mutableSet.add("A") // Tidak ditambahkan karena duplikat
// ========== Map ==========
// Immutable map
val kapital = mapOf(
"Indonesia" to "Jakarta",
"Jepang" to "Tokyo",
"Korea" to "Seoul"
)
println(kapital["Indonesia"]) // Jakarta
println(kapital.keys) // [Indonesia, Jepang, Korea]
println(kapital.values) // [Jakarta, Tokyo, Seoul]
// Mutable map
val mutableMap = mutableMapOf("A" to 1)
mutableMap["B"] = 2
mutableMap["C"] = 3
println(mutableMap) // {A=1, B=2, C=3}
// ========== Collection Operations ==========
val nums = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// Filter
val genap = nums.filter { it % 2 == 0 }
println(genap) // [2, 4, 6, 8, 10]
// Map transformasi
val kaliDua = nums.map { it * 2 }
println(kaliDua) // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
// Reduce
val total = nums.reduce { acc, i -> acc + i }
println(total) // 55
// Fold (dengan initial value)
val totalDari100 = nums.fold(100) { acc, i -> acc + i }
println(totalDari100) // 155
// Sort
val acak = listOf(5, 3, 1, 4, 2)
println(acak.sorted()) // [1, 2, 3, 4, 5]
println(acak.sortedDescending()) // [5, 4, 3, 2, 1]
// GroupBy
val kata = listOf("apel", "anggur", "alpukat", "beras", "bandeng", "ceri")
val grouped = kata.groupBy { it.first() }
println(grouped)
// {a=[apel, anggur, alpukat], b=[beras, bandeng], c=[ceri]}
// Flatten
val nested = listOf(listOf(1, 2), listOf(3, 4), listOf(5))
println(nested.flatten()) // [1, 2, 3, 4, 5]
// Partition
val (lebihDari5, kurangSamaDengan5) = nums.partition { it > 5 }
println(lebihDari5) // [6, 7, 8, 9, 10]
println(kurangSamaDengan5) // [1, 2, 3, 4, 5]
// Chaining operations
val hasil = nums
.filter { it % 2 != 0 } // Ganjil
.map { it * it } // Kuadrat
.sorted()
.take(3) // Ambil 3 terkecil
println(hasil) // [1, 9, 25]
}
8. Extension Function
Extension Function memungkinkan Anda menambahkan fungsi baru ke class yang sudah ada tanpa mengubah kode sumbernya. Ini sangat powerful dan banyak digunakan di Kotlin.
// Extension function pada String
fun String.kebalikan(): String {
return this.reversed()
}
fun String.jumlahKata(): Int {
return this.trim().split("\\s+".toRegex()).size
}
fun String.berulang(n: Int): String {
return this.repeat(n)
}
// Extension function pada Int
fun Int.adalahGenap(): Boolean {
return this % 2 == 0
}
fun Int.faktorial(): Long {
if (this <= 1) return 1
var result = 1L
for (i in 2..this) result *= i
return result
}
fun Int.pangkat(exponent: Int): Long {
var result = 1L
repeat(exponent) { result *= this }
return result
}
// Extension function pada List
fun <T> List<T>.tengah(): T? {
if (isEmpty()) return null
return this[size / 2]
}
fun List<Int>.rataRata(): Double {
if (isEmpty()) return 0.0
return sum().toDouble() / size
}
// Extension property
val String.isPalindrom: Boolean
get() = this == this.reversed()
fun main() {
// Menggunakan extension function
println("Hello".kebalikan()) // olleH
println("Halo Dunia".jumlahKata()) // 2
println("Ha".berulang(3)) // HaHaHa
println(4.adalahGenap()) // true
println(5.adalahGenap()) // false
println(5.faktorial()) // 120
println(2.pangkat(10)) // 1024
val list = listOf(10, 20, 30, 40, 50)
println(list.tengah()) // 30
println(list.rataRata()) // 30.0
// Extension property
println("katak".isPalindrom) // true
println("swift".isPalindrom) // false
println("malam".isPalindrom) // true
}
9. Class & Object
Kotlin mendukung OOP dengan class, inheritance, interface, data class, sealed class, dan enum class.
// Class dasar
class Mahasiswa(val nama: String, val nim: String, var ipk: Double) {
// Property dengan getter custom
val predikat: String
get() = when {
ipk >= 3.5 -> "Cum Laude"
ipk >= 3.0 -> "Sangat Memuaskan"
else -> "Memuaskan"
}
// Method
fun tampilkanInfo() {
println("Nama: $nama, NIM: $nim, IPK: $ipk, Predikat: $predikat")
}
}
// Data class β otomatis generate equals(), hashCode(), toString(), copy()
data class Produk(
val nama: String,
val harga: Int,
val kategori: String = "Umum"
)
// Inheritance
open class Kendaraan(val merk: String) {
open fun jalankan() {
println("$merk mulai berjalan")
}
}
class Mobil(merk: String, val jumlahPintu: Int) : Kendaraan(merk) {
override fun jalankan() {
println("$merk dengan $jumlahPintu pintu melaju! π")
}
}
class Motor(merk: String) : Kendaraan(merk) {
override fun jalankan() {
println("$merk melaju kencang! ποΈ")
}
}
// Interface
interface DapatDihitung {
fun hitungLuas(): Double
fun hitungKeliling(): Double
}
class Lingkaran(val jariJari: Double) : DapatDihitung {
override fun hitungLuas() = Math.PI * jariJari * jariJari
override fun hitungKeliling() = 2 * Math.PI * jariJari
}
// Sealed class β hierarki tertutup
sealed class Result {
data class Success(val data: String) : Result()
data class Error(val message: String) : Result()
data object Loading : Result()
}
fun handleResult(result: Result) {
when (result) {
is Result.Success -> println("β
Data: ${result.data}")
is Result.Error -> println("β Error: ${result.message}")
is Result.Loading -> println("β³ Loading...")
}
}
// Enum class
enum class Warna(val kode: String) {
MERAH("#FF0000"),
HIJAU("#00FF00"),
BIRU("#0000FF");
fun deskripsi() = "Warna $name dengan kode $kode"
}
fun main() {
// Class
val mhs = Mahasiswa("Andi", "12345", 3.7)
mhs.tampilkanInfo()
// Nama: Andi, NIM: 12345, IPK: 3.7, Predikat: Cum Laude
// Data class
val laptop = Produk("Laptop", 15000000, "Elektronik")
val laptopBaru = laptop.copy(harga = 12000000)
println(laptop) // Produk(nama=Laptop, harga=15000000, kategori=Elektronik)
println(laptopBaru) // Produk(nama=Laptop, harga=12000000, kategori=Elektronik)
// Destructuring
val (nama, harga, kategori) = laptop
println("$nama: Rp $harga")
// Inheritance
val mobil = Mobil("Toyota", 4)
mobil.jalankan() // Toyota dengan 4 pintu melaju! π
// Interface
val lingkaran = Lingkaran(7.0)
println("Luas: ${"%.2f".format(lingkaran.hitungLuas())}")
println("Keliling: ${"%.2f".format(lingkaran.hitungKeliling())}")
// Sealed class
handleResult(Result.Success("Data berhasil"))
handleResult(Result.Error("Koneksi gagal"))
handleResult(Result.Loading)
// Enum
println(Warna.MERAH.deskripsi())
// Warna MERAH dengan kode #FF0000
}
10. Coroutine Dasar
Coroutine adalah fitur Kotlin untuk menulis kode async (asynchronous) secara sequential. Coroutine lebih ringan dari thread dan tidak memblokir eksekusi program.
import kotlinx.coroutines.*
fun main() = runBlocking {
// ========== launch β fire and forget ==========
val job = launch {
delay(1000L) // Non-blocking delay
println("Coroutine selesai! π")
}
println("Menunggu...")
job.join() // Tunggu coroutine selesai
println("Selesai!")
// ========== async β mengembalikan nilai ==========
val deferred = async {
delay(1000L)
42 // Return value
}
println("Menunggu hasil...")
val hasil = deferred.await() // Ambil hasilnya
println("Hasil: $hasil") // Hasil: 42
// ========== Multiple async ==========
val angka1 = async {
delay(1000L)
10
}
val angka2 = async {
delay(1500L)
20
}
val total = angka1.await() + angka2.await()
println("Total: $total") // Total: 30
// ========== CoroutineScope ==========
coroutineScope {
val job1 = launch {
delay(500L)
println("Job 1 selesai")
}
val job2 = launch {
delay(300L)
println("Job 2 selesai")
}
// Menunggu semua selesai
}
// ========== withTimeout ==========
try {
withTimeout(1000L) {
delay(2000L) // Akan timeout!
println("Ini tidak akan tercetak")
}
} catch (e: TimeoutCancellationException) {
println("Timeout! β°")
}
}
Coroutine membutuhkan dependency kotlinx-coroutines-core. Untuk Android, gunakan kotlinx-coroutines-android. Di Android, gunakan viewModelScope atau lifecycleScope untuk coroutine yang terikat lifecycle.
11. Quiz Pemahaman
Uji pemahaman Anda tentang Kotlin dengan quiz singkat berikut!