Pada chapter sebelumnya kita berkenalan dengan readln() dan readlnOrNull() sebagai pengganti readLine(). Sekarang kita akan membongkar perilaku keduanya lebih dalam, terutama saat dihadapkan dengan kondisi end-of-file (EOF) dan saat dipakai bersama function parsing seperti toInt(), toDouble(), dan toBoolean(). Pemahaman tentang kapan exception dilempar dan bagaimana rantai pemanggilan method (chaining) bekerja akan membantu kita menulis program CLI yang lebih tangguh.
Perilaku readln() saat EOF #
Function readln() didesain untuk happy path — yaitu ketika stdin masih memiliki baris untuk dibaca. Signature-nya sederhana:
public inline fun readln(): StringKarena tipe kembalian String non-null, kompilator menjamin kita mendapat string tanpa perlu pengecekan null. Konsekuensinya, jika readln() dipanggil ketika stdin sudah EOF, runtime akan melempar RuntimeException dengan pesan mirip berikut:
Exception in thread "main" java.io.EOFException: Input is emptyInilah sebabnya readln() paling cocok dipakai ketika program berjalan di terminal interaktif di mana pengguna selalu mengetik baris input. Untuk program yang membaca file atau pipe, gunakan readlnOrNull() agar kondisi EOF dapat ditangani secara eksplisit.
readlnOrNull() dan Null Safety #
Function readlnOrNull() mengembalikan String? — null ketika stdin mencapai EOF. Penggunaannya mengikuti pola null-safety standar Kotlin:
val baris = readlnOrNull()
if (baris != null) {
println("Anda mengetik: $baris")
} else {
println("Tidak ada input (EOF)")
}
// atau dengan elvis operator
val teks = readlnOrNull() ?: ""
println("Teks aman: $teks")Pilihan antara readln() dan readlnOrNull() bukan soal preferensi gaya, melainkan soal kontrak: kita ingin program berhenti dengan exception saat EOF, atau kita ingin menanganinya secara terprogram.
Parsing dengan Chained Method #
Kombinasi readln() dengan method parsing adalah pola yang sering muncul di program CLI. Karena readln() mengembalikan String, kita dapat langsung memanggil method parsing pada hasilnya:
25
1.75
true
3
85"}
fun main() {
println("Nama:")
val nama = readln()
println("Halo, $nama")
println("Umur:")
val umurText = readln()
val umur = umurText.toInt()
println("Tahun depan: ${umur + 1}")
println("Tinggi (meter):")
val tinggi = readln().toDouble()
println("Tinggi dalam cm: ${tinggi * 100}")
println("Aktif (true/false):")
val aktif = readln().toBoolean()
println("Status aktif: $aktif")
println("Jumlah barang:")
val jumlah = readln().trim().toInt()
val hargaSatuan = 15000
val total = jumlah * hargaSatuan
println("Total: Rp$total")
println("Skor (0-100):")
val skor = readln().toInt()
val kategori = when {
skor >= 90 -> "A"
skor >= 80 -> "B"
skor >= 70 -> "C"
else -> "D"
}
println("Kategori: $kategori")
}Output yang Dihasilkan:
Nama:
Halo, Budi
Umur:
Tahun depan: 26
Tinggi (meter):
Tinggi dalam cm: 175.0
Aktif (true/false):
Status aktif: true
Jumlah barang:
Total: Rp45000
Skor (0-100):
Kategori: BMari kita telaah baris-baris kode di atas:
- Baris 2–4 (
val nama = readln()): functionreadln()membaca satu baris dan mengembalikanStringnon-null. Karena prompt sudah mencetak newline sendiri lewatprintln, baris input pengguna muncul tepat di bawah prompt. - Baris 6–8 (
val umurText = readln()laluumurText.toInt()): pemisahan menjadi dua langkah sengaja dilakukan agar kita melihat rantai pemanggilan secara eksplisit. MethodtoInt()dariStringmengembalikanIntjika teks berisi bilangan bulat valid. - Baris 10–11 (
readln().toDouble()): ini adalah bentuk chained call — hasilreadln()langsung kita panggil methodtoDouble(). Karenareadln()mengembalikanStringnon-null, kita dapat memanggil methodStringsecara langsung tanpa operator?.. - Baris 14 (
readln().toBoolean()): methodtoBoolean()di Kotlin mengembalikantruejika teks (case-insensitive) sama dengan"true", sebaliknyafalse. Tidak sepertiBoolean.parseStringdi Java yang melempar exception, versi Kotlin tidak pernah melempar — string “yes” atau “1” akan menjadifalse. - Baris 18 (
readln().trim().toInt()): kita mengaitkan tiga method:readln()→trim()→toInt(). Methodtrim()menghapus spasi di awal dan akhir, sehingga input" 3 "tetap bisa diparsing menjadi3tanpa galat. - Baris 24–32 (
when { skor >= 90 -> "A" ... }): skor yang sudah diparsing dipakai dalam expressionwhenuntuk menentukan kategori. Karenawhendi Kotlin adalah expression, kita dapat menugaskan hasilnya langsung ke variabelkategori.
Method Parsing yang Umum #
Standard library Kotlin menyediakan dua keluarga method parsing pada String:
| Method | Tipe kembalian | Perilaku saat input invalid |
|---|---|---|
toInt() | Int | Melempar NumberFormatException |
toIntOrNull() | Int? | Mengembalikan null |
toDouble() | Double | Melempar NumberFormatException |
toDoubleOrNull() | Double? | Mengembalikan null |
toBoolean() | Boolean | Selalu berhasil (default false) |
toBooleanStrict() | Boolean | Melempar jika bukan “true”/“false” |
toLong(), toFloat(), toShort() | tipe masing-masing | Melempar saat invalid |
Chained Parsing yang Aman #
Saat kita merantai readln().toInt(), dua sumber galat berbeda muncul: readln() dapat melempar saat EOF, dan toInt() dapat melempar saat teks bukan angka valid. Untuk menangani keduanya secara defensif, gunakan kombinasi readlnOrNull() dan toIntOrNull():
val umur: Int = readlnOrNull()?.toIntOrNull() ?: 0
println("Umur dibaca: $umur")Rantai di atas tidak akan pernah melempar exception apa pun. Jika readlnOrNull() mengembalikan null, safe call ?. menyebarkan null, lalu elvis ?: memberikan nilai default 0.
readln() di Versi Kotlin Lama #
Sebelum Kotlin 1.6, readln() belum ada di standard library. Pengembang terpaksa memakai readLine()!! yang berisiko melempar NullPointerException (bukan RuntimeException) saat EOF. Sejak 1.6, readln() hadir sebagai pengganti yang lebih jelas peringatannya. Jika menemukan kode lama dengan pola readLine() !!, pertimbangkan untuk migrasi ke readln() atau readlnOrNull().
Referensi Lanjutan #
- Kotlin stdlib kotlin.io.readln
— halaman
kotlin.io.readlnuntuk kontrakreadln()danreadlnOrNull() - Kotlin stdlib kotlin.readln
— top-level function
readln()dikotlinpackage
Dengan pemahaman tentang readln() dan rantai parsing, kita siap beranjak ke topik berikutnya: membaca argumen baris perintah (args) yang diteruskan ke main() saat program dijalankan dari terminal.