Mengevaluasi sebuah kondisi berarti menjalankan seluruh pekerjaan yang dibutuhkan untuk menghitung nilainya — termasuk memanggil method pada setiap operand. Operator && dan || menyimpan rahasia yang menghemat pekerjaan itu: begitu kesimpulan sudah pasti dari operand kiri, operand kanan tidak pernah dievaluasi sama sekali. Perilaku ini bernama short-circuit evaluation — evaluasi hubung singkat — dan bukan optimasi opsional yang boleh datang pergi, melainkan jaminan tetap dari spesifikasi bahasa Java. Pada Chapter penutup Section ini kita buktikan perilakunya dengan method yang mencatat setiap pemanggilan, lalu menerapkannya pada pola pemeriksaan null yang dipakai hampir di setiap program Java nyata.

Cara Kerja Short-Circuit #

Aturannya ringkas. Pada a && b: bila a bernilai false, hasil pasti false apa pun nilai b, sehingga b dilewati. Pada a || b: bila a bernilai true, hasil pasti true sehingga b juga dilewati. Untuk membuktikannya, kita perlu operand yang meninggalkan jejak — method catatPembayaran berikut mencetak baris setiap kali dipanggil, sehingga output memperlihatkan dengan pasti method mana yang dieksekusi dan mana yang sama sekali tidak.

java EfekSamping.java
public class EfekSamping {
    static boolean catatPembayaran(int jumlah) {
        System.out.println("  -> method catatPembayaran dipanggil: " + jumlah);
        return jumlah > 0;
    }

    public static void main(String[] args) {
        System.out.println("Uji && : operand kiri menghasilkan false");
        boolean hasil1 = catatPembayaran(0) && catatPembayaran(50000);
        System.out.println("hasil1 = " + hasil1);

        System.out.println("Uji || : operand kiri menghasilkan true");
        boolean hasil2 = catatPembayaran(50000) || catatPembayaran(0);
        System.out.println("hasil2 = " + hasil2);
    }
}

Output yang Dihasilkan:

text
Uji && : operand kiri menghasilkan false
  -> method catatPembayaran dipanggil: 0
hasil1 = false
Uji || : operand kiri menghasilkan true
  -> method catatPembayaran dipanggil: 50000
hasil2 = true

Mari kita telaah bukti pada output tersebut:

  1. Baris 2-5 (static boolean catatPembayaran(...)): method pencatat jejak — setiap pemanggilan mencetak satu baris berisi argumennya, lalu mengembalikan true bila jumlahnya positif.
  2. Uji && (blok pertama): hanya satu baris jejak muncul. catatPembayaran(0) mengembalikan false, sehingga catatPembayaran(50000) di operand kanan tidak pernah dipanggil — hasilnya pun langsung false.
  3. Uji || (blok kedua): kembali hanya satu baris jejak. catatPembayaran(50000) mengembalikan true, operand kanan dilewati, dan hasilnya true.

Bayangkan method yang dilewati tersebut adalah query database atau pemeriksaan berat — penghematannya nyata, dan yang lebih penting, perilakunya dapat diprediksi: Java memang menjamin operand kanan tidak dieksekusi pada situasi tersebut.

Pola Pemeriksaan Berlapis #

Penggunaan short-circuit yang paling penting sehari-hari adalah guard clause berlapis: periksa dulu bahwa referensi tidak null, baru akses anggotanya. Ekspresi s != null && s.length() > 0 aman karena s.length() hanya dieksekusi bila s sudah terbukti bukan null. Urutan operand di sini bukan gaya penulisan — membaliknya mengubah program yang sehat menjadi program yang berhenti karena NullPointerException.

public class CekNullDahulu {
    public static void main(String[] args) {
        String nama = "Budi";
        String kosong = null;

        System.out.println("nama terisi? " + (nama != null && nama.length() > 0));
        System.out.println("kosong aman? " + (kosong != null && kosong.length() > 0));
    }
}

Output yang Dihasilkan:

text
nama terisi? true
kosong aman? false

Baris 6 memeriksa nama yang berisi teks: kedua operand dievaluasi dan hasilnya true. Baris 7 memeriksa kosong yang bernilai null: operand kiri kosong != null bernilai false, sehingga kosong.length() di operand kanan tidak pernah tersentuh — hasilnya false tanpa exception. Pola yang sama berlaku untuk ||: daftar == null || daftar.isEmpty() mengembalikan true dengan aman ketika daftar memang null.

Operator Tanpa Short-Circuit #

Operator & dan | versi boolean menempuh jalan yang berlawanan: kedua operand selalu dievaluasi tanpa kecuali. Perilaku ini sesekali berguna — ketika kedua operand memang harus menjalankan efek sampingnya — tetapi pada pemeriksaan null justru berbahaya. Program berikut sengaja memakai & pada pola guard yang tadi kita buktikan aman dengan &&.

public class TanpaShortCircuit {
    public static void main(String[] args) {
        String kosong = null;
        // operator & mengevaluasi kedua operand -> NullPointerException
        if (kosong != null & kosong.length() > 0) {
            System.out.println("terisi");
        }
    }
}

Eksekusi berkas tersebut berakhir dengan NullPointerException — kita verifikasi langsung bahwa pesan yang tercetak berbunyi Cannot invoke "String.length()" because "<local1>" is null, menunjuk pemanggilan kosong.length() pada operand kanan yang seharusnya tidak perlu dievaluasi. Itulah perbedaan konkret antara & yang penurut menghitung semuanya dan && yang tahu kapan harus berhenti.

Dengan short-circuit, petualangan kita menelusuri operator Java tuntas: aritmetika, penugasan, perbandingan, logika, bitwise, shift, unary, ternary, instanceof, prioritas, dan evaluasi hemat. Semua operator ini akan bekerja keras pada Section berikutnya, tempat program kita mulai berbicara dengan dunia luar — membaca input dari pengguna dan mencetak output terformat rapi.

Referensi #

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

CekNullDahulu.java

Unduh berkas
java
public class CekNullDahulu {
    public static void main(String[] args) {
        String nama = "Budi";
        String kosong = null;

        System.out.println("nama terisi? " + (nama != null && nama.length() > 0));
        System.out.println("kosong aman? " + (kosong != null && kosong.length() > 0));
    }
}

EfekSamping.java

Unduh berkas
java
public class EfekSamping {
    static boolean catatPembayaran(int jumlah) {
        System.out.println("  -> method catatPembayaran dipanggil: " + jumlah);
        return jumlah > 0;
    }

    public static void main(String[] args) {
        System.out.println("Uji && : operand kiri menghasilkan false");
        boolean hasil1 = catatPembayaran(0) && catatPembayaran(50000);
        System.out.println("hasil1 = " + hasil1);

        System.out.println("Uji || : operand kiri menghasilkan true");
        boolean hasil2 = catatPembayaran(50000) || catatPembayaran(0);
        System.out.println("hasil2 = " + hasil2);
    }
}

TanpaShortCircuit.java

Unduh berkas
java
public class TanpaShortCircuit {
    public static void main(String[] args) {
        String kosong = null;
        // operator & mengevaluasi kedua operand -> NullPointerException
        if (kosong != null & kosong.length() > 0) {
            System.out.println("terisi");
        }
    }
}