Sebagian besar kode yang kita tulis jatuh pada dua kategori: statement (perintah yang dijalankan tanpa menghasilkan nilai) dan expression (kode yang menghasilkan nilai). Pada chapter ini kita akan membedah perbedaan keduanya, melihat bagaimana Kotlin mengubah if, when, dan try menjadi expression, dan membandingkan dengan Java yang memperlakukan ketiganya sebagai statement. Pemahaman ini membuat kode Kotlin jauh lebih ringkas.
Definisi: Statement vs Expression #
Expression adalah konstruksi bahasa yang menghasilkan nilai. Contoh paling sederhana adalah literal 42, operasi aritmetika 1 + 2, atau pemanggilan function hitungTotal(5000, 3).
Statement adalah konstruksi yang melakukan aksi tetapi tidak menghasilkan nilai. Contoh: deklarasi variabel val x = 5, perulangan for, atau pemanggilan println(...).
Pada banyak bahasa turunan C (termasuk Java), if, switch, dan try adalah statement — mereka menjalankan cabang kode tetapi tidak menghasilkan nilai yang bisa ditugaskan ke variabel. Kotlin berbeda: ketiganya adalah expression yang mengembalikan nilai.
if sebagai Expression #
Pada Kotlin, if dapat berdiri sendiri sebagai statement (untuk efek samping) atau dipakai sebagai expression yang menghasilkan nilai:
val suhu = 32
val status = if (suhu >= 30) "panas" else "sejuk"
// status == "panas"Padanannya dalam Java memerlukan statement if-else eksplisit yang menugaskan ke variabel di tiap cabang:
String status;
if (suhu >= 30) {
status = "panas";
} else {
status = "sejuk";
}Versi Kotlin lebih ringkas: satu baris ekspresi menggantikan lima baris Java. Kompilator menyimpulkan tipe hasil if dari tipe kedua cabang; bila kedua cabang memiliki tipe berbeda, hasilnya adalah supertype umum (misal Any).
Contoh Lengkap dengan if, when, dan try #
Berikut program yang memadukan ketiganya sebagai expression:
fun main() {
// if sebagai expression
val suhu = 32
val status = if (suhu >= 30) "panas" else "sejuk"
println("Cuaca: $status")
// when sebagai expression dengan banyak cabang
val kode = 404
val pesan = when (kode) {
200 -> "Sukses"
in 300..399 -> "Pengalihan"
404 -> "Tidak ditemukan"
in 500..599 -> "Kesalahan server"
else -> "Tidak diketahui"
}
println("Kode $kode -> $pesan")
// try sebagai expression
val angka = amanParse("42")
println("Hasil parse: $angka")
// if bersarang sebagai expression
val nilai = 78
val predikat = if (nilai >= 90) {
"A"
} else if (nilai >= 80) {
"B"
} else if (nilai >= 70) {
"C"
} else {
"D"
}
println("Nilai $nilai -> predikat $predikat")
}
fun amanParse(input: String): Int {
return try {
input.toInt()
} catch (e: NumberFormatException) {
0
}
}Output yang Dihasilkan:
Cuaca: panas
Kode 404 -> Tidak ditemukan
Hasil parse: 42
Nilai 78 -> predikat CMari kita bedah bagian kunci:
- Baris 4 (
val status = if (suhu >= 30) "panas" else "sejuk") — kedua cabang menghasilkanString, sehinggastatusbertipeString. - Baris 9-15 (
val pesan = when (kode) { ... }) —whenmenggantikanswitchJava; setiap cabang adalah expression. Cabangin 300..399memakai range check, danelsewajib bila kompilator tidak dapat membuktikan kelelahan cabang. - Baris 18 (
val angka = amanParse("42")) — functionamanParsememakaitrysebagai expression; bloktrymengembalikan hasilinput.toInt(), dan blokcatchmengembalikan0sebagai fallback. - Baris 21-31 (
val predikat = if (...) { ... } else if ...) —if-else if-elsebertingkat tetap valid sebagai expression; setiap cabang menulis string sebagai nilai terakhirnya.
Aturan Tipe pada Expression if dan when #
Saat if atau when dipakai sebagai expression, kompilator menerapkan aturan tipe berikut:
- Semua cabang harus menghasilkan tipe yang kompatibel.
- Bila satu cabang bertipe
Stringdan cabang lainInt, hasil menjadiAny(supertype umum). - Bila salah satu cabang tidak mengembalikan nilai (hanya
returnatau melempar exception), cabang tersebut tidak dihitung dalam inferensi tipe. - Cabang
Nothing(misal melempar exception) tidak memengaruhi inferensi tipe cabang lain.
val hasil: Any = if (kondisi) "teks" else 42 // Any sebagai supertype
val tetap: String = if (kondisi) "ok" else fail("gagal") // fail() -> Nothingtry sebagai Expression #
Pada Java, blok try-catch adalah statement; di Kotlin, try adalah expression yang mengembalikan nilai dari baris terakhirnya:
fun amanParse(input: String): Int {
return try {
input.toInt()
} catch (e: NumberFormatException) {
0
}
}Function amanParse di atas mengembalikan Int dari blok try saat parsing berhasil, atau Int 0 dari blok catch saat gagal. Tanpa fitur ini, kita perlu variabel sementara di luar try, yang menambah boilerplate.
when Lebih Kuat dari switch #
when adalah pengganti switch Java yang jauh lebih ekspresif. Selain konstanta, when mendukung pola berikut:
| Pola | Contoh |
|---|---|
| Konstanta | 200 -> "Sukses" |
| Range | in 300..399 -> "Pengalihan" |
| Tipe | is String -> "teks" |
| Ekspresi bebas | kode % 2 == 0 -> "genap" |
| Multi-nilai | 200, 201, 202 -> "Sukses" |
Berbeda dengan switch Java yang memerlukan break di tiap case, when otomatis berhenti pada cabang yang cocok — tidak ada fall-through.
Perbandingan dengan Java #
Tabel berikut merangkum perbedaan treatment if, switch/when, dan try antara Kotlin dan Java:
| Konstruksi | Kotlin | Java |
|---|---|---|
if | Expression dan statement | Hanya statement |
when / switch | Expression; tanpa fall-through | Statement; fall-through dengan break |
try | Expression; mengembalikan nilai | Statement; butuh variabel luar |
for | Hanya statement | Hanya statement |
while / do-while | Hanya statement | Hanya statement |
Referensi Lanjutan #
- Kotlin basic syntax
— panduan resmi perbedaan statement dan expression dalam
ifsertawhen - Kotlin control flow
— rujukan
ifdanwhensebagai expression di Kotlin
Memperlakukan if, when, dan try sebagai expression mengurangi boilerplate dan membuat kode deklaratif. Dengan pola ini, kita siap melihat bagaimana kita menamai setiap simbol yang kita buat — yaitu aturan identifier dan keyword Kotlin — pada chapter Identifier dan Keywords.