Java: kenapa 1 == 1 true sedangkan 1000 == 1000 false?

By | 16 November 2024

Java baru-baru ini menjadi bahasa pemrograman favorit saya, beralih dari PHP. Alasannya, saya cukup benci dengan kondisi dimana tipe data suatu variable yang dapat berubah, yang hal ini belum saya temui (dan mungkin tidak akan) di Java.

Saat pertama menggunakan Java, saya cukup bingung dengan operator perbandingannya. Memang, kita bisa menggunakan == atau != sama seperti di PHP maupun bahasa pemrograman lainnya. Tapi, ternyata Java memperlakukan operator perbandingan tersebut dengan berbeda.

Perhatikan kode berikut:

<?php
$a = 1;
$b = 1;

$x = 1000;
$y = 1000;

echo $a == $b; // true
echo $x == $y; // true

Di PHP, kedua perbandingan tersebut akan menghasilkan true, bahkan jika menggunakan strict comparison sekalipun.

Kemudian, perhatikan kode berikut:

Integer a = 1;
Integer b = 1;
        
System.out.println(a == b); // true
        
Integer x = 1000;
Integer y = 1000;
        
System.out.println(x == y); // false

Jadi kenapa bisa begitu?

Pertama, Integer bukanlah tipe data primitif melainkan wrapper untuk tipe data int.

Hah? Apa?

Jadi, Java menyediakan wrapper atau semacam utilitas untuk tipe data primitif seperti int, boolean hingga doubleWrapper ini menyediakan kemampuan seperti konversi antar tipe data dengan mudah, manipulasi value dan sebagainya.

Melakukan komparasi tipe data wrapper tidak boleh dilakukan menggunakan ==, melainkan menggunakan method equals()

Nah, apalagi?

== dan equals() memiliki perilaku yang berbeda. Perbedaan utamanya adalah == membandingkan referensi objek di memory, bukan nilainya. Sementara itu, equals() membandingkan nilai atau isi didalam objek. Sebelum membahas kedua hal tersebut, kita perlu membahas Integer Caching terlebih dahulu.

Integer caching merupakan metode optimasi untuk objek Integer dimana Java menggunakan satu objek yang sama (cached object) untuk rentang nilai -128 hingga 127.

Jika kamu perhatikan definisi integer caching tersebut, seharusnya kamu sudah tau jawaban dari pertanyaan yang saya buat di judul posting ini.

Jadi, jawaban dari “di Java, kenapa 1 == 1 adalah true sedangkan 1000 == 1000 adalah false?” adalah integer caching.

Penjelasannya?

Oke, kita mulai dari variable a dan b yang sama-sama bernilai 1. Ketika kita membuat variable dengan nilai yang termasuk dalam rentang -128 hingga 127, Java akan memeriksa apakah nilai 1 tersebut sudah ada dalam cached object atau belum. Jika sudah ada, maka Java tidak akan membuat objek baru lagi, tetapi menggunakan objek yang sudah ada. Objek baru hanya akan dibuat jika memang objek dengan nilai 1 belum ada di memory.

Sampai disini, di memory sudah ada objek dengan nilai 1 yang anggap saja dibuat oleh variable a. Oleh karena itu, ketika kita membuat variable b yang nilainya 1, Java tidak akan membuat objek baru tetapi menggunakan referensi objek yang sama seperti variable a.

Jadi, variable a dan b akan menggunakan referensi objek yang sama di memory, sehingga jika kita menggunakan perbandingan == akan menghasilkan true.

Lalu kenapa 1000 == 1000 hasilnya false?

Merujuk kepada definisi integer caching, nilai 1000 sudah berada diluar jangkauan integer caching. Dengan demikian, saat kita membuat variable x dengan nilai 1000, Java tidak akan melakukan pemeriksaan cached object, melainkan langsung membuat object baru. Begitu juga dengan variable y. Maka, variable x dan y akan memiliki referensi objek yang berbeda di memory sehingga perbandingan == akan menghasilkan false.

Kapan menggunakan == dan equals() ?

Kembali lagi, == boleh digunakan jika yang dibandingkan adalah tipe data primitif. Tetapi jika membandingkan wrapper, maka yang perlu digunakan adalah equals().

Pertama, mari gunakan == dan equals() untuk wrapper.

Integer x = 1000;
Integer y = 1000;
        
System.out.println(x == y); // false
System.out.println(x.equals(y)); // true

Secara logika dan akal sehat, 1000 adalah 1000 sehingga x == y seharusnya menghasilkan true, tetapi nyatanya malah false. Dengan demikian, untuk menghasilkan perbandingan yang benar, kita harus menggunakan equals() jika membandingkan wrapper.

Jadi, jangan karena 1 == 1 menghasilkan true sehingga kamu menggunakan == untuk membandingkan wrapper, karena itu hanya akan menghasilkan true selama nilai yang dibandingkan berada dalam rentang integer caching.

Selanjutnya, mari gunakan == dan equals() untuk tipe data primitif.

int x = 1000;
int y = 1000;
        
System.out.println(x == y); // true
System.out.println(x.equals(y)); // error

Pada contoh ini, perbandingan x == y menghasilkan true dan memang seharusnya true. Tapi kenapa .equals() malah error? Hal tersebut karena equals() merupakan method yang ada didalam wrapper sehingga tidak bisa digunakan untuk perbandingan tipe data primitif.

Apa lagi?

Judul posting ini sebetulnya hanya clickbait saja, namun hal ini dalam rangka mengingatkan saya untuk memperdalam basic Java seperti tipe data primitif dan wrapper-nya, kemudian juga operator perbandingan.

Sementara itu, equals() juga memiliki perilaku lain, misalnya saat membandingkan null. Hmm….

Okey, terima kasih sudah membaca sampai disini!

Tinggalkan Balasan