Pada tingkat paling dasar, setiap nilai di memori hanyalah barisan bit — angka 0 dan 1. Operator bitwise bekerja langsung pada representasi biner tersebut: & (AND), | (OR), ^ (XOR), dan ~ (NOT). Teknik ini dipakai untuk menyimpan banyak penanda dalam satu angka, membaca format berkas, memproses protokol jaringan, hingga operasi kriptografi ringan. Pada Chapter ini kita pelajari keempat operator tersebut pada tipe int, membaca hasilnya melalui Integer.toBinaryString, lalu menerapkannya pada pola bitmask hak akses yang banyak dipakai di kode nyata.
Empat Operator Bitwise #
Operator & membandingkan bit demi bit dan menghasilkan 1 hanya bila kedua bit bernilai 1. Operator | menghasilkan 1 bila salah satu bit bernilai 1, sedangkan ^ menghasilkan 1 bila kedua bit berbeda. Operator ~ adalah operator unary yang membalik setiap bit — semua 0 menjadi 1 dan sebaliknya. Java memungkinkan kita menulis angka dalam literal biner dengan awalan 0b, sehingga contoh berikut dapat dibaca dengan jelas bit demi bit.
public class OperasiBit {
public static void main(String[] args) {
int a = 0b1100; // 12
int b = 0b1010; // 10
System.out.println("a = " + Integer.toBinaryString(a) + " (" + a + ")");
System.out.println("b = " + Integer.toBinaryString(b) + " (" + b + ")");
System.out.println("a & b = " + Integer.toBinaryString(a & b) + " (" + (a & b) + ")");
System.out.println("a | b = " + Integer.toBinaryString(a | b) + " (" + (a | b) + ")");
System.out.println("a ^ b = " + Integer.toBinaryString(a ^ b) + " (" + (a ^ b) + ")");
System.out.println("~a = " + Integer.toBinaryString(~a) + " (" + ~a + ")");
}
}Output yang Dihasilkan:
a = 1100 (12)
b = 1010 (10)
a & b = 1000 (8)
a | b = 1110 (14)
a ^ b = 110 (6)
~a = 11111111111111111111111111110011 (-13)Mari kita telaah baris-baris kode di atas:
- Baris 3-4 (
int a = 0b1100;danint b = 0b1010;): dua operand dalam literal biner —0b1100bernilai desimal12dan0b1010bernilai10. - Baris 6-7 (
Integer.toBinaryString(...)): method dari classIntegeryang mencetak representasi biner tanpa nol di depan, sehingga0b0110tampil sebagai110. - Baris 8 (
a & b): bit ke-empat bernilai1pada kedua operand hanya di posisi paling kanan kedua — hasilnya1000atau desimal8. - Baris 9-10 (
a | bdana ^ b): OR menghasilkan1110(14) karena menggabungkan semua bit yang aktif; XOR menghasilkan110(6) karena hanya bit yang berbeda yang bertahan. - Baris 11 (
~a): seluruh 32 bit dibalik sehingga hasilnya negatif — kita bedah alasannya di callout berikut.
Bitmask untuk Flag Hak Akses #
Pola pemakaian bitwise yang paling lazim adalah bitmask: setiap bit mewakili satu penanda, dan satu variabel int sanggup menampung 32 penanda sekaligus. Menggabungkan penanda memakai |, menguji satu penanda memakai & lalu membandingkan hasilnya dengan 0, menambah penanda memakai |= compound assignment, dan mencabut penanda memakai &= bersama ~. Contoh berikut menerapkan pola tersebut pada hak akses sederhana.
public class BitmaskHakAkses {
public static void main(String[] args) {
final int BACA = 0b0001; // 1
final int TULIS = 0b0010; // 2
final int HAPUS = 0b0100; // 4
int hakBudi = BACA | TULIS; // gabung flag
int hakSiti = BACA | TULIS | HAPUS;
System.out.println("hakBudi = " + Integer.toBinaryString(hakBudi));
System.out.println("hakSiti = " + Integer.toBinaryString(hakSiti));
System.out.println("Budi bisa menulis? " + ((hakBudi & TULIS) != 0));
System.out.println("Budi bisa menghapus? " + ((hakBudi & HAPUS) != 0));
System.out.println("Siti bisa menghapus? " + ((hakSiti & HAPUS) != 0));
hakBudi |= HAPUS; // tambah flag HAPUS
System.out.println("Budi bisa menghapus sekarang? " + ((hakBudi & HAPUS) != 0));
hakSiti &= ~HAPUS; // cabut flag HAPUS
System.out.println("Siti masih bisa menghapus? " + ((hakSiti & HAPUS) != 0));
}
}Output yang Dihasilkan:
hakBudi = 11
hakSiti = 111
Budi bisa menulis? true
Budi bisa menghapus? false
Siti bisa menghapus? true
Budi bisa menghapus sekarang? true
Siti masih bisa menghapus? falsePerhatikan mekanisme di balik output tersebut:
- Baris 3-5: tiga konstanta
finalmenempatkan setiap hak pada posisi bit yang berbeda — nilai1,2, dan4adalah bilangan berpangkat dua. - Baris 7-8:
BACA | TULISmenghasilkan0b0011(tampil11) danBACA | TULIS | HAPUSmenghasilkan0b0111(tampil111) — tiga penanda hidup dalam satu angka. - Baris 13-15:
hakBudi & TULISmenghasilkan2(bukan0) sehingga Budi dinyatakan boleh menulis;hakBudi & HAPUSmenghasilkan0sehingga Budi belum boleh menghapus. - Baris 17 (
hakBudi |= HAPUS;): bit HAPUS dinyalakan tanpa mengganggu bit lain — jawaban berubah menjaditrue. - Baris 20 (
hakSiti &= ~HAPUS;):~HAPUSadalah...11111011; operasi AND menjaga semua bit lain tetap utuh sambil mematikan bit HAPUS.
Satu keluarga operator bit masih belum kita sentuh: operator shift yang menggeser posisi bit ke kiri dan ke kanan. Menggeser bit ternyata cara tercepat mengalikan atau membagi dengan pangkat dua, dan pada bilangan negatif perilakunya menyimpan kejutan. Chapter berikutnya mengupas <<, >>, dan >>> sampai ke contoh angka negatif.
Referensi #
- Java Language Specification — Bab 15 Expressions
- Class Integer — Java SE 25 API
- Oracle Dev.java — Learn Java
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
BitmaskHakAkses.java
Unduh berkaspublic class BitmaskHakAkses {
public static void main(String[] args) {
final int BACA = 0b0001; // 1
final int TULIS = 0b0010; // 2
final int HAPUS = 0b0100; // 4
int hakBudi = BACA | TULIS; // gabung flag
int hakSiti = BACA | TULIS | HAPUS;
System.out.println("hakBudi = " + Integer.toBinaryString(hakBudi));
System.out.println("hakSiti = " + Integer.toBinaryString(hakSiti));
System.out.println("Budi bisa menulis? " + ((hakBudi & TULIS) != 0));
System.out.println("Budi bisa menghapus? " + ((hakBudi & HAPUS) != 0));
System.out.println("Siti bisa menghapus? " + ((hakSiti & HAPUS) != 0));
hakBudi |= HAPUS; // tambah flag HAPUS
System.out.println("Budi bisa menghapus sekarang? " + ((hakBudi & HAPUS) != 0));
hakSiti &= ~HAPUS; // cabut flag HAPUS
System.out.println("Siti masih bisa menghapus? " + ((hakSiti & HAPUS) != 0));
}
}
OperasiBit.java
Unduh berkaspublic class OperasiBit {
public static void main(String[] args) {
int a = 0b1100; // 12
int b = 0b1010; // 10
System.out.println("a = " + Integer.toBinaryString(a) + " (" + a + ")");
System.out.println("b = " + Integer.toBinaryString(b) + " (" + b + ")");
System.out.println("a & b = " + Integer.toBinaryString(a & b) + " (" + (a & b) + ")");
System.out.println("a | b = " + Integer.toBinaryString(a | b) + " (" + (a | b) + ")");
System.out.println("a ^ b = " + Integer.toBinaryString(a ^ b) + " (" + (a ^ b) + ")");
System.out.println("~a = " + Integer.toBinaryString(~a) + " (" + ~a + ")");
}
}