Operator pembanding menghasilkan nilai Boolean yang menjadi dasar percabangan program. Kotlin membedakan dua jenis kesetaraan: kesetaraan struktural (==) yang membandingkan isi, dan kesetaraan referensial (===) yang membandingkan identitas memori. Pada chapter ini kita akan membahas keenam operator pembanding, perilaku == yang dipetakan ke equals(), lalu perbedaan kedua jenis kesetaraan yang sering membingungkan pemula dari Java.
Daftar Operator Pembanding #
Kotlin mendukung operator relasi yang sama dengan bahasa turunan C:
| Operator | Arti | Function | Hasil untuk a=10, b=3, c=10 |
|---|---|---|---|
== | sama dengan (struktural) | equals() | a == c → true |
!= | tidak sama dengan | equals() | a != b → true |
< | lebih kecil | compareTo() < 0 | a < b → false |
> | lebih besar | compareTo() > 0 | a > b → true |
<= | lebih kecil atau sama | compareTo() <= 0 | a <= c → true |
>= | lebih besar atau sama | compareTo() >= 0 | a >= c → true |
Untuk tipe primitif seperti Int, kompilator menerjemahkan a == b menjadi pembandingan nilai langsung. Untuk tipe reference, kompilator mengeluarkan pemanggilan equals(), dengan pemeriksaan null otomatis, sehingga ekspresi a == b aman bahkan jika a atau b bernilai null.
Kesetaraan Struktural vs Referensial #
Kesetaraan struktural (==) membandingkan isi dua objek melalui method equals(). Kesetaraan referensial (===) membandingkan apakah dua variabel menunjuk ke instance yang sama di memori. Operator !== adalah negasi dari ===.
fun main() {
val a = 10
val b = 3
val c = 10
println("a == b: ${a == b}")
println("a != b: ${a != b}")
println("a == c: ${a == c}")
println("a < b: ${a < b}")
println("a > b: ${a > b}")
println("a <= c: ${a <= c}")
println("a >= c: ${a >= c}")
val daftar1 = listOf(1, 2, 3)
val daftar2 = listOf(1, 2, 3)
val daftar3 = daftar1
println("daftar1 == daftar2: ${daftar1 == daftar2}")
println("daftar1 === daftar2: ${daftar1 === daftar2}")
println("daftar1 === daftar3: ${daftar1 === daftar3}")
println("daftar1 !== daftar2: ${daftar1 !== daftar2}")
val teks1 = StringBuilder("halo")
val teks2 = StringBuilder("halo")
println("StringBuilder ===: ${teks1 === teks2}")
println("StringBuilder ==: ${teks1 == teks2}")
val banding = a.compareTo(b)
println("a.compareTo(b) = $banding")
}Output yang Dihasilkan:
a == b: false
a != b: true
a == c: true
a < b: false
a > b: true
a <= c: true
a >= c: true
daftar1 == daftar2: true
daftar1 === daftar2: false
daftar1 === daftar3: true
daftar1 !== daftar2: true
StringBuilder ===: false
StringBuilder ==: false
a.compareTo(b) = 1Mari kita uraikan bagian penting pada contoh di atas:
a == cmenghasilkantruekarena nilaiInt10 dibandingkan secara langsung. Kompilator menggunakan instruksi bytecode primitif tanpa pemanggilan function.daftar1 == daftar2menghasilkantrue.Listdi Kotlin mengimplementasikanequals()dengan membandingkan elemen satu per satu, sehingga dua list dengan isi yang sama dianggap setara.daftar1 === daftar2menghasilkanfalse. Meskipun isinya sama, kedua variabel menunjuk ke objekListyang berbeda di memori heap.daftar1 === daftar3menghasilkantruekarenadaftar3 = daftar1membuat kedua variabel menunjuk ke instance yang sama.StringBuilder ==menghasilkanfalse. Berbeda denganList,StringBuildertidak meng-overrideequals(), sehingga==jatuh ke implementasi defaultObject.equals()yang membandingkan referensi memori.a.compareTo(b)mengembalikan bilangan bulat: negatif jikaa < b, nol jika sama, positif jikaa > b. Operator<,>,<=,>=dipetakan ke functioncompareTo()ini.
Perilaku compareTo dan Comparable #
Operator <, >, <=, dan >= dipanggil melalui function compareTo() yang mengembalikan Int. Aturan yang harus dipatuhi: tanda hasil konsisten dengan operator pembanding. Jika a.compareTo(b) < 0, maka a < b harus true. Class yang mengimplementasikan Comparable<T> otomatis mendukung keempat operator relasi tanpa perlu menulis operator fun tambahan.
String Comparison #
String di Kotlin dibandingkan secara struktural melalui equals(), sehingga "halo" == "halo" selalu true. Jika ingin membandingkan identitas memori (misalnya untuk verifikasi string pooling), gunakan ===. Untuk perbandingan leksikografis yang lebih canggih (case-insensitive, locale-aware), gunakan String.compareTo(other, ignoreCase) atau API Collator dari Java.
val nama1 = "Budi"
val nama2 = "budi"
println(nama1.equals(nama2, ignoreCase = true)) // trueReferensi Lanjutan #
- Operator overloading
— bagian comparison operator (
compareTo) pada panduan resmi - Equality
— penjelasan resmi
==dan===di Kotlin
Dengan pemahaman tentang ==, ===, dan operator relasi, kita dapat membangun kondisi percabangan. Selanjutnya kita akan menggabungkan beberapa kondisi menggunakan operator logika &&, ||, dan ! pada chapter berikutnya.