2.
Variabel dan Perhitungan
Menyimpan Karakter
Variabel bertipe
char dapat menyimpan satu kode
karakter. Variabel tipe ini menempati 16 bit atau 2 byte memori karena semua
karakter dalam Java disimpan sebagai kode Unicode. Untuk mendeklarasikan dan
menginisialisasi sebuah variabel karakter karakterKu,
Anda dapat menggunakan statemen:
char karakterKu = ‘X’;
Ini
menginisialisasi variabel dengan representasi karakter Unicode dari huruf ‘X’.
Anda perlu selalu menempatkan kutip tunggal sebagai pembatas untuk literal
karakter pada sebuah statemen seperti contoh ini, ‘X’. Ini diperlukan agar
kompilator dapat membedakan antara karakter ‘X’ dari variabel dengan nama X.
Perhatikan bahwa Anda tidak bisa menggunakan kutip ganda sebagai pembatas
karakter karena kutip ganda dipakai untuk pembatas string karakter. Sebuah
string karakter seperti “X” berbeda dari literal bertipe char ‘X’.
Runtun
Escape Karakter
Umumnya,
karakter-karakter yang dapat Anda ketikkan dari papantik atau keyboard
merupakan fungsi kunci yang disediakan dan himpunan kode karakter yang
diperlukan oleh fungsi tersebut sesuai dengan kebutuhan sistem Anda. Agar Anda
bisa memasukkan sembarang karakter Unicode sebagai bagian dari kode sumber
program, Anda dapat mendefinisikan karakter-karakter Unicode dengan menetapkan
representasi heksadesimal dari kode-kode karakter pada sebuah runtun escape.
Runtun escape adalah sebuah cara alternatif dalam menetapkan sebuah karakter
yang didefinisikan dengan kode. Sebuah simbol backslash, \, mengindikasikan
awal dari runtun escape.
Anda menciptakan
sebuah runtun escape untuk karakter Unicode dengan mengawali empat dijit
heksadesimal dari kode karakter dengan simbol \u. Karena pengkodean Unicode
untuk huruf X adalah nilai heksadesimal 0x0058, maka Anda dapat mendeklarasikan
dan mendefinisikan karakterKu dengan
statemen berikut:
char karakterKu = ‘\u0058’;
Anda menempatkan
runtun escape di antara dua tanda-kutip tunggal untuk mendefinisikan literal karakter.
Hasilnya sama seperti statemen sebelumnya dimana Anda menggunakan ‘X’ sebagai
nilai awal untuk karakterKu. Anda bisa
memberikan sembarang karakter Unicode dengan cara ini, tentu saja sepanjang
Anda mengetahui kodenya.
Karena simbol
backslash mengindikasikan awal dari sebuah runtun escape, maka Anda harus
selalu menggunakan runtun escape \\ untuk menetapkan sebuah karakter backslash
sebagai literal karakter atau sebagai string teks.
Seperti yang
telah Anda ketahui, Anda menuliskan string karakter dengan mengapitnya di
antara dua tanda-kutip ganda, dan Anda menuliskan literal karakter dengan
mengapitnya di antara dua tanda-kutip tunggal. Karena alasan ini, Anda juga
memerlukan runtun escape \’ dan \” untuk menetapkan kedua karakter ini
(tanda-kutip tunggal dan tanda-kutip ganda). Misalnya, untuk menampilkan
keluaran:
“Hari Jum’at, kami akan
pergi ke pantai”, ia berkata dengan riang.
Anda bisa
menuliskan:
System.out.println(“\”Hari
Jum\’at, kami akan pergi ke pantai\”, ia berkata dengan riang.”);
Ada sejumlah
runtun escape lain yang Anda bisa gunakan untuk mendefinisikan
karakter-karakter kontrol:
\b
|
Backspace
|
\g
|
Form
feed
|
\n
|
New
line
|
\r
|
Carriage
return
|
\t
|
Tab
|
Aritmatika
Karakter
Anda dapat
melakukan aritmatika terhadap variabel char.
Dengan karakterKu memuat karakter ‘X’,
statemen:
karakterKu += 1; // Menginkremen ke karakter berikutnya
akan menyebabkan
nilai dari karakterKu diubah menjadi
‘Y’. Ini karena kode Unicode untuk ‘Y’ bernilai satu lebih tinggi daripada kode
untuk ‘X’. Anda dapat menggunakan operator inkremen ++ untuk menambah kode yang
tersimpan pada karakterKu dengan
menuliskan:
++karakterKu; // Menginkremen ke karakter berikutnya
Ketika Anda
menggunakan variabel bertipe char
pada sebuah ekspresi aritmatik, nilainya akan dikonversi menjadi tipe int sebelum perhitungan dilakukan. Anda
bisa menuliskan statemen-statemen yang melibatkan nilai-nilai bertipe char berikut:
char aKar = 0;
char bKar = ‘\u0028’;
aKar = (char)(2*bKar + 8);
Statemen-statemen
di atas menyebabkan variabel aKar memuat kode untuk huruf X, yaitu 0x0058.
Latihan
|
Aritmatika
dengan Kode-Kode Karakter
|
Contoh ini akan
mendemonstrasikan operasi-operasi aritmatik yang melibatkan nilai-nilai bertipe
char:
public class
PerhitunganKodeKarakter {
public static void main(String[] args){
char huruf1 = 'A'; // huruf1 adalah 'A'
char huruf2 = (char)(huruf1+1); //
huruf2 adalah 'B'
char huruf3 = huruf2; // huruf3 juga 'B'
System.out.println("Berikut
adalah sebuah runtun huruf: "+ huruf1 +
huruf2
+ (++huruf3));
// huruf3 sekarang adalah 'C'
System.out.println("Berikut
adalah kode desimal untuk tiap huruf tersebut:\n"+
huruf1 + ": " +
(int)huruf1 +
" " + huruf2 + ":
" + (int)huruf2 +
" " + huruf3 + ":
" + (int)huruf3);
}
}
Contoh ini akan
menghasilkan keluaran:
Berikut adalah sebuah runtun
huruf: ABC
Berikut adalah kode desimal
untuk tiap huruf tersebut:
A: 65 B: 66 C: 67
Penjelasan
Tiga statemen
pertama pada main() mendefinisikan
tiga variabel bertipe char:
char huruf1 = 'A'; // huruf1 adalah 'A'
char huruf2 =
(char)(huruf1+1); // huruf2 adalah 'B'
char huruf3 = huruf2; // huruf3 juga 'B'
Konversi tipe
eksplisit menjadi char dari nilai
awal untuk huruf2 merupakan hal
penting. Tanpa itu, kode program tidak akan bisa dikompilasi. Ekspresi huruf1 + 1 menghasilkan nilai bertipe int, dan kompilator tidak akan
melakukan konversi tipe implisit secara otomatis menjadi char karena potensi hilangnya informasi.
Statemen
selanjutnya menampilkan ketiga karakter:
System.out.println("Berikut
adalah sebuah runtun huruf: "+ huruf1 +
huruf2
+ (++huruf3));
Dua karakter
pertama yang ditampilkan adalah yang disimpan pada huruf1 dan huruf2.
Karakter ketiga adalah nilai yang disimpan pada huruf3 setelah variabel tersebut diinkremen sebesar 1.
Secara default,
metode println() memperlakukan
variabel bertipe char sebagai
karakter yang akan ditampilkan. Anda tetap bisa menampilkan nilai yang disimpan
pada sebuah variabel char sebagai
nilai numeris dengan melakukan konversi tipe eksplisit menjadi int. Statemen selanjutnya
mendemonstrasikan ini:
System.out.println("Berikut
adalah kode desimal untuk tiap huruf tersebut:\n"+
huruf1 + ": " +
(int)huruf1 +
" " + huruf2 + ":
" + (int)huruf2 +
" " + huruf3 + ":
" + (int)huruf3);
Statemen ini
menampilkan nilai dari ketiga variabel sebagai karakter yang diikuti dengan
nilai desimalnya.
Tentu, Anda bisa
jadi ingin melihat kode karakter sebagai nilai heksadesimal. Anda dapat
menampilkan sembarang nilai bertipe int
sebagai string heksadesimal menggunakan metode toHexString dari kelas Integer
pada pustaka standar. Tambahkan statemen keluaran berikut di akhir metode main():
System.out.println("Berikut
adalah kode heksadesimal untuk tiap huruf:\n"+
huruf1 + ": " +
Integer.toHexString(huruf1) +
"
" + huruf2 + ": " + Integer.toHexString(huruf2) +
" " + huruf3 + ": " +
Integer.toHexString(huruf3));
}
Statemen ini
akan menampilkan kode-kode karakter sebagai nilai-nilai heksadesimal:
Berikut adalah kode
heksadesimal untuk tiap huruf:
A: 41 B: 42 C: 43
Metode toHexString() menghasilkan representasi
string dari argumennya. Di sini, Anda memiliki nama dari sebuah variabel
bertipe char sebagai argumen untuk
ketiga pemanggilan metode ini. Anda bisa juga menempatkan sembarang ekspresi
yang menghasilkan nilai bertipe int
sebagai argumen dari metode toHexString().
Karena metode ini mensyaratkan argumen dengan tipe int, maka kompilator akan melakukan konversi tipe implisit secara
otomatis menjadi tipe int untuk tiap
argumen huruf1, huruf2, dan huruf3.
Operasi-Operasi Bitwise
Seperti yang
telah Anda ketahui, semua variabel integer yang telah didiskusikan
direpresentasikan secara internal sebagai bilangan biner. Sebuah nilai bertipe
int memuat 32 dijit biner atau 32 bit. Anda dapat memanipulasi bit-bit tersebut
menggunakan operator-operator bitwise yang disediakan:
&
|
AND
|
|
|
OR
|
^
|
XOR
|
~
|
Komplemen
|
Gambar 2-5
Tiap operator
ini diterapkan pada bit-bit pada operand-operandnya dengan cara berikut:
* Operator AND
bitwise, &, mengkombinasikan bit-bit pada kedua operandnya sehingga jika
bit pertama (bit dari operand pertama) DAN bit kedua (bit dari operand kedua)
maka hasilnya adalah bit 1. Selain kondisi itu, hasilnya adalah bit 0.
* Operator OR
bitwise, |, mengkombinasikan bit-bit pada kedua operandnya sehingga jika salah
satu (bit dari operand pertama ATAU bit dari operand kedua) bernilai 1 maka
hasilnya adalah bit 1. Selain kondisi itu, hasilnya adalah bit 0.
* Operator XOR
bitwise, ^, mengkombinasikan bit-bit pada kedua operandnya sehingga jika keduanya
(bit dari operand pertama dan bit dari operand kedua) bernilai sama maka
hasilnya adalah bit 0. Selain kondisi itu, hasilnya adalah bit 1.
* Operator
komplemen, ~, mengambil satu operand dengan menginversi (membalikkan) semua
bit-bit dari operand tersebut, sehingga tiap bit 1 menjadi bit 0, dan tiap bit
0 menjadi bit 1.
Anda dapat
melihat efek dari operator-operator ini pada contoh-contoh yang ditunjukkan
pada Gambar 2-5. Gambar tersebut
menunjukkan dijit-dijit biner yang mengkonstruksi operand-operand dan hasil
operasi. Ketiga operasi biner diterapkan terhadap pasangan-pasangan bit pada
operand-operandnya secara bergiliran. Operator komplemen hanya membalikkan
keadaan dari tiap bit pada operandnya sehingga bit 1 menjadi bit 0 dan bit 0
menjadi bit 1.
Konversi dari
biner ke heksadesimal adalah hal mudah. Setiap grup empat biner dari kanan
dikelompokkan menjadi satu dijit heksadesimal. Sebagai contoh, nilai dari a
pada ilustrasi sebelumnya adalah:
Biner
|
0110
|
0110
|
1100
|
1101
|
Nilai Desimal
|
6
|
6
|
12
|
13
|
Heksadesimal
|
6
|
6
|
C
|
D
|
Jadi, nilai dari
variabel a pada heksadesimal adalah 0x66CD, dimana prefiks 0x mengindikasikan
bahwa ini adalah sebuah nilai heksadesimal. Variabel b pada ilustrasi memiliki
nilai heksadesimal 0x000F.
Menggunakan
Operator AND dan OR
Anda bisa
melihat operator & dari perspektif lain: ia memaksa sebuah bit menjadi 0
jika bit mask bernilai 0 dan membiarkan bit apa adanya jika bit mask adalah 1.
Jadi, operator & memberikan Anda cara untuk menon-aktifkan bit-bit tertentu
dalam sebuah word, dan membiarkan bit-bit lain apa adanya. Anda bisa
menciptakan sebuah mask dengan bit-bit 0 pada posisi-posisi yang ingin Anda
jadikan menjadi bit 0 dan bit-bit 1 di posisi-posisi lain. Sama halnya,
operator | memaksa sebuah bit menjadi 1 ketika bit mask bernilai 1, dan
membiarkan bit apa adanya ketika bit mask bernilai 0.
Operator & dan
| merupakan operator-operator bitwise yang paling sering digunakan. Anda bisa
menggunakan satu bit sebagai indikator keadaan yang menentukan apakah sesuatu
perlu ditampilkan, ketika nilai bit 1, atau tidak ditampilkan, ketika nilai bit
0. Ambil contoh sederhana, untuk memilih bit ketiga dari kanan pada variabel int bernama indikator, Anda bisa menuliskan:
bitKetiga = indikator &
0x4; // Memilih bit ketiga
Bit ketiga dari
variabel bitKetiga akan bernilai
sama dengan bit ketiga pada variabel indikator
dan semua bit lain dari variabel bitKetiga
akan bernilai 0.
Heksadesimal
|
Biner
|
||||
indikator
|
0xFF07
|
1111
|
1111
|
0000
|
0111
|
Nilai mask
|
0x4
|
0000
|
0000
|
0000
|
0100
|
indikator &
0x4
|
0x4
|
0000
|
0000
|
0000
|
0100
|
Semua nilai ini
memiliki 32 bit, karena bertipe int.
Yang ditunjukkan di sini hanya 16 bit saja, hanya untuk menunjukkan pada Anda
bagaimana hal ini dilakukan. Nilai mask menetapkan semua bit bernilai 0 pada
hasil kecuali untuk bit ketiga. Di sini, hasil ekspresi adalah tak-nol karena
bit ketiga pada indikator adalah bit
1.
Di sisi lain,
jika variabel indikator yang memuat nilai 0xFF09, maka hasilnya akan berbeda:
Heksadesimal
|
Biner
|
||||
indikator
|
0xFF09
|
1111
|
1111
|
0000
|
1001
|
Nilai mask
|
0x4
|
0000
|
0000
|
0000
|
0100
|
indikator &
0x4
|
0x0
|
0000
|
0000
|
0000
|
0000
|
Hasil ekspresi
sekarang adalah nol karena bit ketiga dari indikator adalah bit 0.
Seperti yang
telah dijelaskan, Anda dapat menggunakan operator | untuk mengaktifkan bit
tertentu. Sebagai contoh, untuk mengaktifkan bit ketiga pada indikator, Anda dapat menuliskan:
indikator = indikator | 0x4; // Mengaktifkan bit ketiga
Anda dapat
melihat bagaimana ini dilakukan pada indikator:
Heksadesimal
|
Biner
|
||||
indikator
|
0xFF09
|
1111
|
1111
|
0000
|
1001
|
Nilai mask
|
0x4
|
0000
|
0000
|
0000
|
0100
|
indikator | 0x4
|
0xFF0D
|
1111
|
1111
|
0000
|
1101
|
Seperti yang
dapat Anda lihat, efeknya adalah mengaktifkan bit ketiga dari indikator. Semua bit lain dipertahankan
apa adanya. Tentu, jika bit ketiga telah aktif sebelumnya, maka bit tersebut
tetap aktif (bernilai 1).
Anda dapat pula
menggunakan operator-operator bitwise dengan formasi op=. Pengaktifan bit
ketiga pada variabel indikator
umumnya dilakukan dengan:
indikator |= 0x4;
Statemen ini
tampak lebih ringkas dan mudah dibaca.
Untuk Menon-aktifkan
bit tertentu, Anda bisa menggunakan operator & kembali, dengan sebuah mask
dengan bit 0 untuk bit yang ingin Anda non-aktifkan, dan dengan bit 1 untuk
bit-bit lain. Untuk menon-aktifkan bit ketiga dari variabel indikator, Anda bisa menuliskan:
indikator &= ~0x4; // Menon-aktifkan bit ketiga
Operator ~
menegasikan atau membalikkan keadaan bit. Literal 0x4 adalah sebuah nilai
dengan bit ketiga adalah bit 0 dan bit-bit lain adalah bit 1. Penerapan
operator ~ pada literal tersebut akan membalikkan keadaan dari tiap bit,
sehingga bit-bit 0 menjadi 1 dan bit 1 menjadi bit 0. Dengan variabel indikator
memiliki nilai 0xFF07, maka hal ini dapat dijelaskan menjadi:
Heksadesimal
|
Biner
|
||||
indikator
|
0xFF09
|
1111
|
1111
|
0000
|
1001
|
Nilai mask
|
0x4
|
0000
|
0000
|
0000
|
0100
|
~0x4
|
0xFFFB
|
1111
|
1111
|
1111
|
1011
|
indikator &~0x4
|
0xFF03
|
1111
|
1111
|
0000
|
0011
|
Anda akan
melihat operator-operator bitwise ini dalam program contoh berikut.
Latihan
|
Operasi-Operasi
AND dan OR Bitwise
|
Contoh ini
adalah sejumlah contoh operasi yang telah Anda lihat sebelumnya:
import static
java.lang.Integer.toBinaryString;
public class OperasiBitwise
{
public static void main(String[] args) {
int indikator = 0xFF07;
int pilihBit3 = 0x4; // Mask untuk
memilih bit ketiga
// Malakukan AND bitwise untuk memilih
bit ketiga pada indikator
System.out.println("indikator =
" +
toBinaryString(indikator));
System.out.println("pilihBit3 =
" +
toBinaryString(pilihBit3));
indikator &= pilihBit3;
System.out.println("indikator &
pilihBit3 = " +
toBinaryString(indikator));
// Melakukan OR bitwise untuk mengatifkan
bit ketiga
indikator = 0xFF09;
System.out.println("\nindikator =
"+
toBinaryString(indikator));
System.out.println("pilihBit3 =
"+
toBinaryString(pilihBit3));
indikator |= pilihBit3;
System.out.println("indikator |
pilihBit3 = " +
toBinaryString(indikator));
// Sekarang menon-aktifkan kembali bit
ketiga
indikator &= ~pilihBit3;
System.out.println("\nBit ketiga
pada nilai sebelumnya dari indikator" +
" telah dinon-aktifkan");
System.out.println("indikator &
~pilihBit3 = " +
toBinaryString(indikator));
}
}
Contoh ini
menghasilkan keluaran berikut:
indikator = 1111111100000111
pilihBit3 = 100
indikator & pilihBit3 =
100
indikator = 1111111100001001
pilihBit3 = 100
indikator | pilihBit3 =
1111111100001101
Bit ketiga pada nilai
sebelumnya dari indikator telah dinon-aktifkan
indikator & ~pilihBit3 =
1111111100001001
Penjelasan
Contoh ini
menggunakan fragmen-fragmen kode yang telah dijelaskan sebelumnya sehingga Anda
dapat melihat bagaimana hal itu dapat dipakai sesuai yang telah dijelaskan.
Salah satu kapabilitas baru yang dikenalkan di sini adalah kegunaan dari metode
toBinaryString() yang didefinisikan
pada kelas Integer. Diberikan
statemen impor statik di bagian atas kode sumber program sehingga Anda tidak
perlu menyebutkan nama kelas Integer
setiap kali menggunakan metode tersebut. Metode toBinaryString() menghasilkan sebuah string yang memuat
representasi biner dari nilai bertipe int
yang dilewatkan sebagai argumen kepada metode itu. Anda dapat melihat dari
keluaran untuk nilai dari pilihBit3
bahwa string tidak mencantumkan nol-nol depan. Tentu, keluaran akan lebih baik
dengan nol-nol depan ditampilkan, tetapi Anda perlu memahami lebih jauh tentang
bagaimana menangani string untuk melakukannya.
Menggunakan
Operator XOR (Exclusive OR)
Operator ^
memiliki kemampuan menukar dua nilai dengan cara yang menakjubkan. Dimisalkan
bahwa Anda mengeksekusi tiga statemen berikut:
a ^= b;
b ^= a;
a ^= b;
Efek dari ketiga
statemen ini adalah menukar nilai a dan b, tetapi Anda perlu mengingat bahwa
hal ini hanya bisa dilakukan terhadap integer. Anda dalat mencobanya untuk sembarang
nilai a dan b, misalnya 0xD00F dan 0xABAD. Statemen pertama mengubah a menjadi
sebuah nilai baru:
a ^= b
|
Heksadesimal
|
Biner
|
|||
a
|
0xD00F
|
1101
|
0000
|
0000
|
1111
|
b
|
0xABAD
|
1010
|
1011
|
1010
|
1101
|
a dari a^b
|
0x7BA2
|
0111
|
1011
|
1010
|
0010
|
Statemen
selanjutnya, yang menghitung nilai baru dari b menggunakan nilai baru dari a:
b ^= a
|
Heksadesimal
|
Biner
|
|||
a
|
0x7BA2
|
0111
|
1011
|
1010
|
0010
|
b
|
0xABAD
|
1010
|
1011
|
1010
|
1101
|
b dari b^a
|
0xD00F
|
1101
|
0000
|
0000
|
1111
|
Jadi, sekarang b
memiliki sebuah nilai yang sama dengan nilai a semula. Sekarang langkah
terakhir, yang menghitung sebuah nilai baru untuk a menggunakan nilai baru dari
b:
a ^= b
|
Heksadesimal
|
Biner
|
|||
a
|
0x7BA2
|
0111
|
1011
|
1010
|
0010
|
b
|
0xD00F
|
1101
|
0000
|
0000
|
1111
|
a dari a^b
|
0xABAD
|
1010
|
1011
|
1010
|
1101
|
Lihatlah bahwa
nilai a sekarang adalah nilai semula dari b. Jadi, Anda bisa menukar dua nilai
integer, tanpa memerlukan memori ekstra. Tetapi Anda tidak bisa melakukannya
pada nilai-nilai titik-mengambang.
Satu hal yang
perlu Anda ketahui: Kehati-hatian diperlukan saat menginisialisasi variabel
bertipe byte dan bertipe short menggunakan nilai heksadesimal.
Sebagai contoh, Anda bisa jadi tergoda untuk menginisialisasi sebuah variabel
bertipe byte dengan nilai biner 1111
1111 menggunakan statemen berikut:
byte semuaBitSatu = 0xFF; // Salah!!!
Pada dasarnya,
hasil ini menyebabkan error kompilasi. Literal 0xFF adalah bertipe int, jadi nilai binernya adalah 0000
0000 0000 0000 0000 0000 1111 1111. Nilai biner ini adalah ekivalen dengan
nilai desimal 128, yang berada di luar rentang tipe byte. Nilai byte yang Anda inginkan adalah 1111 1111, yang ekivalen
dengan nilai desimal -1, jadi cara yang benar untuk menginisialisasi semuBitSatu adalah dengan menuliskan:
byte semuaBitSatu = 0xFFFFFFFF; // Benar!!!
Sekarang,
kompilator akan membuang bit-bit orde-tinggi untuk memberikan hasil yang Anda
inginkan.
Operasi-Operasi
Penggeseran
Mekanisme lain
yang dapat Anda lakukan terhadap variabel-variabel integer pada level bit
adalah penggeseran. Anda dapat menggeser bit-bit pada sebuah integer ke kiri atau
ke kanan. Anda dapat memandang proses penggeseran dijit-dijit biner ke kanan
atau ke kiri sebagai operasi pembagian atau pemangkatan berbasis 2. Penggeseran
nilai biner dari desimal 3, 0011, ke kiri sejauh satu bit sama dengan
mengalikannya dengan dua. Nilai itu akan menjadi 0110, yang bernilai desimal 6.
Penggeseran nilai desimal 3 ke kanan sejauh satu bit akan membagi nilai
tersebut dengan 2, yang menghasilkan biner 0001, atau desimal 1.
Gambar 2-6
Java memiliki
tiga operator penggeseran:
<<
|
Menggeser
ke kiri, dengan mengisi nol-nol dari kanan.
|
>>
|
Menggeser
ke kanan, dengan mempropagasikan bit tanda dari kiri.
|
>>>
|
Menggeser
ke kanan, dengan mengisi nol-nol dari kiri.
|
Efek dari tiap
operator penggeseran ditampilkan pada Gambar 2-6. Tentu, jika bit orde-tinggi
pada operasi >> pada Gambar 2-6 adalah nol, maka tidak akan ada tiga nol
pada ujung paling-kiri dari hasil.
Operasi-operasi
penggeseran seringkali dipakai bersamaan dengan operator-operator bitwise
lainnya yang telah didiskusikan sebelumnya. Pada banyak sistem operasi, sebuah
nilai 32-bit kadangkala dipakai untuk menyimpan beberapa nilai. Misalnya, Anda
dapat menyimpan dua koordinat 16-bit pada sebuah word 32-bit. Ini
diilustrasikan pada Gambar 2-7.
Gambar 2-7
Gambar 2-7
menunjukkan bagaimana operasi-operasi penggeseran dapat dipakai untuk
mengekstraksi 16 bit kiri atau kanan dari variabel nilai. Anda dapat melihat di sini mengapa Anda memiliki operasi
penggeseran kiri ekstra yang mempropagasi bit paling-kiri. Ketika bit tanda
tidak dipropagasikan, operasi penggeseran kanan tidak memiliki interpretasi
numeris untuk nilai-nilai negatif karena bit tanda diperlakukan sama seperti
bit lainnya, dan nol-nol disisipkan dari kanan. Ketika bit tanda
dipropagasikan, efeknya pada nilai-nilai negatif sama seperti pada nilai-nilai
positif.
Latihan
|
Menggunakan
Operasi-Operasi Penggeseran
|
Contoh ini
menggunakan operator-operator penggeseran bersama dengan operator-operator
bitwise lain untuk memaketkan empat nilai bertipe char menjadi sebuah variabel bertipe long:
import static
java.lang.Long.toHexString;
public class PaketKarakter {
public static void main(String[] args) {
char hurufA = 'A';
char hurufB = 'B';
char hurufC = 'C';
char hurufD = 'D';
long dipaket = 0L;
dipaket = hurufD; // Menyimpan D
// Menggeser dan menambah huruf
berikutnya - C
dipaket = (dipaket << 16) | hurufC;
// Menggeser dan menambah huruf berikutnya
- B
dipaket = (dipaket << 16) | hurufB;
// Menggeser dan menambah huruf
berikutnya - A
dipaket = (dipaket << 16) | hurufA;
System.out.println("dipaket sekarang
memuat 0x" + toHexString(dipaket));
// Sekarang mengekstraksi huruf-huruf dan
menampilkannya
long mask = 0xFFFF; // 16 bit
paling-kanan sebagai 1
// Mengekstraksi huruf paling-kanan
char huruf = (char)(dipaket & mask);
System.out.println("Dari kanan ke
kiri, huruf-huruf pada dipaket:");
System.out.println(" " + huruf
+ " 0x" + toHexString(huruf));
dipaket >>= 16; // Membuang huruf
paling-kanan
// Mengekstraksi huruf paling-kanan yang
baru
huruf = (char)(dipaket & mask);
System.out.println(" " + huruf +
" 0x" + toHexString(huruf));
dipaket >>= 16; // Membuang huruf
paling-kanan
// Mengekstraksi huruf paling-kanan yang
baru
huruf = (char)(dipaket & mask);
System.out.println(" " + huruf
+ " 0x" + toHexString(huruf));
dipaket >>= 16; // Membuang huruf
paling-kanan
// Mengekstraksi huruf paling-kanan yang
baru
huruf = (char)(dipaket & mask);
System.out.println(" " + huruf
+ " 0x" + toHexString(huruf));
}
}
Keluaran dari
program ini:
dipaket sekarang memuat
0x44004300420041
Dari kanan ke kiri,
huruf-huruf pada dipaket:
A 0x41
B 0x42
C 0x43
D 0x44
Penjelasan
Empat statemen
pertama pada main() mendefinisikan
variabel-variabel yang diinisialisasi dengan huruf-huruf yang akan dipaketkan
ke dalam variabel, dipaket, yang bertipe long
dan didefinisikan pada statemen kelima pada main(). Proses pemaketan diawali
dengan menyimpan karakter pertama pada dipaket:
dipaket = hurufD; //
Menyimpan D
Ingat bahwa 16
bit paling-kanan pada dipaket sekarang
memuat kode karakter D. Kode karakter huruf D ini akhirnya digeser ke 16 bit
paling kiri pada dipaket. Statemen
berikutnya menyisipkan huruf berikutnya, C, ke dalam dipaket:
dipaket = (dipaket <<
16) | hurufC;
Huruf C ini
disisipkan dengan lebih dahulu menggeser ke kiri isi dari variabel dipaket sejauh 16 bit, dan kemudian
hasilnya di-OR-kan dengan hurufC. Pada titik ini, 32 bit paling-kiri dari dipaket adalah nol dan 32 bit
paling-kanan memuat D yang diikuti dengan C.
Dua statemen
berikutnya mengulangi proses yang sama untuk menyisipkan B dan A:
dipaket = (dipaket <<
16) | hurufB;
dipaket = (dipaket <<
16) | hurufA;
Sekarang
variabel dipaket memuat kode dari keempat karakter dengan urutan D, C, B, dan
A. Keluaran ditampilkan oleh statemen berikut:
System.out.println("Dari
kanan ke kiri, huruf-huruf pada dipaket:");
Statemen ini
menggunakan metode toHexString()
yang didefinisikan pada kelas Long
untuk menghasilkan sebuah string yang memuat representasi heksadesimal dari
nilai dari dipaket. Karena Anda menempatkan
statemen impor statik untuk nama metode ini, Anda tidak perlu menyertakan nama
kelas. Anda dapat melihat dari keluaran bahwa variabel dipaket sekarang memuat
empat kode karakter 0x44, 0x43, 0x42, dan 0x41, yang merupakan kode untuk huruf
D sampai A.
Program kemudian
mendemonstrasikan bagaimana Anda dapat menggunakan operator penggeseran dan
operator AND untuk mengekstraksi empat nilai char dari dipaket.
Langkah pertama adalah mendefinisikan sebuah mask untuk menyeleksi 16 bit
paling-kanan pada sebuah nilai bertipe long:
long mask = 0xFFFF; // 16
bit paling-kanan sebagai 1
Statemen
selanjutnya menggunakan mask tersebut untuk memilih kode karakter paling-kanan
pada dipaket:
char huruf = (char)(dipaket
& mask);
Konversi tipe
eksplisit menjadi tipe char dari
hasil dari operasi AND terhadap mask
dengan dipaket diperlukan karena
kompilator tidak akan melakukan konversi tipe implisit secara otomatis dari
tipe long ke tipe char.
Dua statemen
berikutnya menampilkan penjelasan diikuti dengan huruf pertama dan kodenya:
System.out.println("Dari
kanan ke kiri, huruf-huruf pada dipaket:");
System.out.println("
" + huruf + " 0x" + toHexString(huruf));
Untuk
mendapatkan karakter berikutnya, Anda membuang karakter yang baru saja diekstraksi
dan melakukan operasi AND terhadap hasilnya dengan mask sekali lagi:
dipaket >>= 16; //
Membuang huruf paling-kanan
huruf = (char)(dipaket &
mask);
Hasil dari
operasi penggeseran kanan disimpan kembali ke dalam dipaket, jadi operasi AND terhadap mask dengan dipaket akan
mengekstraksi huruf berikutnya. Ekstraksi terhadap dua huruf selanjutnya
diulangi dengan proses yang sama.
Metode-Metode
untuk Operasi-Operasi Bitwise
Selain fasilitas
dasar untuk operasi-operasi pada level bit, Anda juga memiliki sejumlah metode
yang tersedia pada kelas-kelas pustaka Java. Metode-metode yang
mengimplementasikan operasi-operasi bitwise didefinisikan pada kelas Integer dan Long pada paket java.lang. Metode-metode pada kelas Integer hanya berlaku untuk nilai-nilai
bertipe int, dan metode-metode pada
kelas Long hanya berlaku untuk
nilai-nilai bertipe long. Kedua
kelas mendefinisikan metode-metode berikut:
Metode
|
Penjelasan
|
bitCount(arg)
|
Menghasilkan
jumlah bit 1 pada sebuah integer biner yang disuplai sebagai arg. Nilai baliknya bertipe int.
|
highestOneBit(arg)
|
Menghasilkan
sebuah integer dengan 1 bit tunggal pada posisi yang berkaitan 1 bit
paling-kiri dari arg. Nilai balik
yang dihasilkan bertipe sama dengan arg.
|
lowestOneBit(arg)
|
Menghasilkan
sebuah integer dengan 1 bit tunggal pada posisi yang berkaitan 1 bit
paling-kanan dari arg. Nilai balik
yang dihasilkan bertipe sama dengan arg.
|
numberOfLeadingZeros(arg)
|
Menghasilkan
banyak bit 0 yang ada sebelum bit 1 paling-kiri pada arg. Nilai balik yang dihasilkan bertipe int. Jika arg adalah
nol, maka metode ini menghasilkan banyak total bit pada arg, yaitu 32 bit untuk tipe int
dan 64 bit untuk tipe long.
|
numberOfTrailingZeros(arg)
|
Menghasilkan
banyak bit 0 yang ada setelah bit 1 paling-kanan pada arg. Nilai balik yang dihasilkan bertipe int. Jika arg adalah
nol, maka metode ini menghasilkan banyak total bit pada arg, yaitu 32 bit untuk tipe int
dan 64 bit untuk tipe long.
|
reverse(arg)
|
Menghasilkan
nilai yang didapatkan dengan membalikkan urutan bit-bit pada arg. Nilai balik bertipe sama dengan arg.
|
rotateLeft(arg,
jarak)
|
Menghasilkan
nilai yang didapatkan dengan merotasi bit-bit pada arg ke kiri sejauh jarak
posisi bit, dimana jarak adalah
sebuah nilai bertipe int. Rotasi
kiri berarti bahwa bit-bit yang digeser di sebelah kiri ditempatkan ke
posisi-posisi bit sebelah kanan. Nilai balik yang dihasilkan bertipe sama
dengan arg.
|
rotateRight(arg,
jarak)
|
Menghasilkan
nilai yang didapatkan dengan merotasi bit-bit pada arg ke kanan sejauh jarak
posisi bit, dimana jarak adalah
sebuah nilai bertipe int. Rotasi kanan
berarti bahwa bit-bit yang digeser di sebelah kanan ditempatkan ke
posisi-posisi bit sebelah kiri. Nilai balik yang dihasilkan bertipe sama
dengan arg.
|
Ketika Anda
ingin menerapkannya tersebut pada sebuah nilai yang bertipe int, Anda memanggil metode dari kelas Integer, dan ketika Anda ingin
menerapkannya tersebut pada sebuah nilai yang bertipe long, Anda memanggil metode dari kelas Long.
Untuk menghitung
berapa banyak bit 1 pada sebuah integer, jika Anda melakukannya sendiri, hal
itu memerlukan usaha yang ekstra. Dengan metode bitCount(), Anda bisa memperoleh hasil hanya menggunakan satu
statemen. Perhatikan contoh-contoh berikut.
Pertama,
dimisalkan Anda mendefinisikan sebuah variabel integer sebagai berikut:
int data = 0x0F00; // Data ini adalah: 0000 0000 0000 0000 0000
1111 0000 0000
Anda sekarang
dapat menerapkan metode bitCount()
pada variabel tersebut. Anda perlu menggunakan metode pada kelas Integer karena data bertipe int:
int banyakBit1 =
Integer.bitCount(data); // Hasil adalah 4
Variabel banyakBit1 akan memiliki nilai 4 karena
data memuat empat bit 1. Anda
menggunakan metode pada kelas Integer
karena data bertipe int. Jika Anda menerapkannya pada
sebuah argumen bertipe long, Anda
harus menggunakan metode dari kelas Long.
Berikut adalah
definisi dari variabel integer lain, kali ini bertipe long:
long angka =
0xF00000000000000FL;
Pola bit pada angka memiliki byte pertama 1111 0000
dan byte terakhir sebagai 0000 1111; semua byte lain bernilai nol. Perhatikan
simbol L di akhir literal sangat penting di sini. Tanpa simbol itu, Anda
dipandang memberikan literal bertipe int,
dan tipe int hanya memiliki 32 bit,
dan kompilator akan mengeluarkan pesan error.
Anda dapat
merotasi bit-bit pada angka ke kiri
sejauh dua bit dengan statemen berikut:
long hasil =
Long.rotateLeft(angka, 2);
Variabel hasil akan ditetapkan menjadi sebuah
nilai dimana byte pertama adalah 0xC0, byte terakhir adalah 0x3F, dan semua bit
lain adalah nol. Bit-bit pada angka
digeser ke kiri sejauh 2 posisi bit, dan dua bit 1 yang digeser di kiri akan
ditempatkan ke posisi kanan.
Latihan
|
Metode-Metode
Untuk Operasi Bit
|
Anda akan
melihat efek dari beberapa metode yang telah didiskusikan. Contoh ini juga menunjukkan
bagaimana metode-metode pada kelas Integer
dan Long digunakan.
import static
java.lang.Long.*;
public class CobaMetodeBit {
public static void main(String[] args) {
long angka = 0xF00000000000000FL;
System.out.println("Variabel
angka:\n" + toBinaryString(angka));
long hasil = rotateLeft(angka,2);
System.out.println("Variabel angka
dirotasi ke kiri 2 bit:\n" +
toBinaryString(hasil));
hasil = rotateRight(angka, 3);
System.out.println("Variabel angka
dirotasi ke kanan 3 bit:\n" +
toBinaryString(hasil));
hasil = reverse(hasil);
System.out.println("Hasil sebelumnya
dibalik:\n" + toBinaryString(hasil));
System.out.println("Banyak bit 1
pada angka:\n" + bitCount(angka));
}
}
Keluaran
program:
Variabel angka:
1111000000000000000000000000000000000000000000000000000000001111
Variabel angka dirotasi ke
kiri 2 bit:
1100000000000000000000000000000000000000000000000000000000111111
Variabel angka dirotasi ke
kanan 3 bit:
1111111000000000000000000000000000000000000000000000000000000001
Hasil sebelumnya dibalik:
1000000000000000000000000000000000000000000000000000000001111111
Banyak bit 1 pada angka:
8
Variabel-Variabel dengan Sejumlah Nilai Integer
Tertentu
Anda akan
memerlukan variabel-variabel yang dapat memiliki nilai-nilai tertentu. Sebagai
contoh, dimisalkan bahwa Anda ingin mendefinisikan sebuah variabel integer dengan
nama Hari, yang akan menyimpan
sebuah nilai integer yang merepresentasikan sebuah hari. Variabel tersebut
idealnya dibatasi untuk tujuh nilai yang mungkin, satu untuk tiap hari dari
Senin sampai Minggu. Inilah di mana enumerasi menjadi pilihan. Anda bisa
mendefinisikan sebuah enumerasi untuk kasus ini dengan statemen deklarasi
berikut:
enum Hari {Senin, Selasa,
Rabu, Kamis, Jumat, Sabtu, Minggu}
Ini
mendefinisikan sebuah tipe data baru, Hari,
untuk variabel-variabel yang hanya dapat menyimpan satu atau lebih nilai yang
diapit sepasang kurung kurawal. Nama Senin, Selasan, dan seterusnya sampai
Minggu dinamakan dengan konstanta enumerasi, dan hanya dapat diakses melalu
variabel Hari. Perhatikan tidak
adanya tanda titik-koma di akhir definisi enumerasi Hari. Karena Anda sedang mendefinisikan sebuah tipe data di sini,
maka titik-koma tidak diperlukan.
Dengan tipe data
ini, Anda sekarang dapat mendefinisikan variabel hariSeminggu seperti ini:
Hari hariSeminggu =
Hari.Selasa;
Statemen ini
mendeklarasikan variabel hariSeminggi
sebagai tipe data Hari, dan
menginisialisasinya dengan nilai Selasa.
Perhatikan bahwa konstanta enumerasi harus diawali dengan nama tipe enumerasi.
Jika Anda tidak menyebutkannya, kompilator tidak akan mengenali konstanta
tersebut.
Sebuah enumerasi
dapat memuat sebanyak mungkin konstanta enumerasi yang Anda perlukan. Berikut
adalah sebuah tipe enumerasi untuk setiap bulan dalam setahun:
enum Bulan {Januari,
Februari, Maret, April, Mei, Juni, Juli,
Agustus, September, Oktober,
November, Desember}
Anda dapat juga
mendefinisikan sebuah variabel dengan tipe data Bulan seperti ini:
Bulan sekarang =
Bulan.September; // Menginisialisasi
dengan September
Jika Anda
nantinya ingin mengubah nilai yang disimpan pada variabel sekarang, Anda dapat mengubah nilainya menjadi konstanta enumerasi
yang berbeda:
sekarang = Bulan.Oktober;
Variabel sekarang sekarang memuat konstanta
enumerasi Oktober. Perhatikan contoh
berikut.
Latihan
|
Menggunakan
Enumerasi
|
Berikut adalah
sebuah program yang mendefinisikan enumerasi Hari dan beberapa variabel bertipe data Hari:
public class CobaEnumerasi {
// Mendefinisikan sebuah tipe enumerasi
untuk semua hari dalam seminggu
enum Hari {Senin, Selasa, Rabu, Kamis,
Jumat, Sabtu, Minggu}
public static void main(String[] args) {
// Mendefinisikan tiga variabel bertipe
Hari
Hari kemarin = Hari.Kamis;
Hari sekarang = Hari.Jumat;
Hari besok = Hari.Sabtu;
// Menampilkan nilai dari tiap variabel
bertipe Hari
System.out.println("Sekarang adalah
" + sekarang);
System.out.println("Besok adalah
" + besok);
System.out.println("Kemarin adalah
" + kemarin);
}
}
Keluaran
program:
Sekarang adalah Jumat
Besok adalah Sabtu
Kemarin adalah Kamis
Penjelasan
Kode ini sendiri
sebenarnya apa yang telah Anda lihat sebelumnya. Ini merupakan deklarasi atas
tipe enumerasi Hari, yang diikuti
dengan metode main() yang memuat
definisi dari tiga variabel bertipe Hari.
Anda kemudian memiliki statemen-statemen keluaran untuk ketiganya.
Keluaran program
tampak menarik diamati. Yang ditampilkan bukanlah nilai numerik dari tipe Hari, tetapi namanya. Ini merupakan
cara default dimana sebuah nilai bertipe enumerasi direpresentasikan sebagai
sebuah string karena nama lebih penting daripada nilai pada tipe enumerasi.
Perhatikan bahwa
karena statemen yang mendefinisikan Hari
mendefinisikan sebuah tipe baru, Anda tidak bisa memosisikannya di dalam tubuh
metode main(). Definisi untuk Hari
dapat pula ditempatkan di dalam file sumber terpisah dengan nama Hari.java.
Variabel Boolean
Variabel bertipe
boolean hanya dapat memilih salah
satu dari dua nilai, true atau false. Nilai true dan false keduanya
adalah literal boolean. Tipe data boolean berasal dari nama seorang
matematikawan George Boolean, yang menemukan aljabar Boolean. Anda dapat
mendefinisikan sebuah variabel bertipe boolean
dinamakan keadaan menggunakan
statemen berikut:
boolean keadaan = true;
Statemen ini
juga menginisialisasi variabel keadaan
dengan nilai true.
Anda dapat pula
menetapkan nilai dari sebuah variabel boolean
pada statemen penugasan. Misalnya, statemen:
keadaan = false;
menetapkan nilai
dari variabel keadaan menjadi false.
Pada titik ini,
Anda tidak melakukan banyak hal pada variabel boolean, selain menetapkan nilanya menjadi true atau false. Tetapi,
pada bab selanjutnya, Anda akan melihat bahwa variabel boolean dapat menjadi berguna dalam konteks pembuatan keputusan
dalam program.
Sejumlah
operator mengkombinasikan nilai-nilai boolean,
termasuk operator AND boolean, OR boolean, dan negasi boolan. Hal ini akan
didiskusikan pada bab selanjutnya.
Keutamaan Operator
Keutamaan
operator menentukan urutan eksekusi operator pada sebuah statemen. Ekspresi
aritmatik sederhana seperti 3+4*5 menghasilkan nilai 23 karena operasi
perkalian dieksekusi lebih dahulu daripada operasi penjumlahan. Setiap operator
dalam Java memiliki aturan keutamaan operator, seperti diunjukkan pada tabel
berikut. Operator-operator dengan keutamaan lebih tinggi dieksekusi lebih
dahulu daripada operator-operator dengan keutamaan lebih rendah. Derajat
keutamaan tertinggi adalah operator-operator pada baris atas pada tabel, dengan
keutamaan lebih rendah pada baris-baris yang ada di bawahnya. Operator-operator
yang ada pada baris yang sama memiliki keutamaan yang sama.
Grup Keutamaan
Operator
|
Asosiatifitas
|
(), [],
postfiks ++, postfiks --
|
kiri
|
Unary +, unary
-, prefiks ++, prefiks --, ~, !
|
kanan
|
(tipe), new
|
kiri
|
*, /, %
|
kiri
|
+, -
|
kiri
|
<<,
>>, >>>
|
kiri
|
<, <=,
>, >=, instanceof
|
kiri
|
==, !=
|
kiri
|
&
|
kiri
|
^
|
kiri
|
|
|
kiri
|
&&
|
kiri
|
||
|
kiri
|
?:
|
kiri
|
=, +=, -=, *=,
/=, %=, <<=, >>=, >>>=, &=, |=, ^=
|
kanan
|
Secara definisi,
operator postfiks ++ mengubah nilai dari operandnya setelah operator-operator
lain pada ekspresi dieksekusi lebih dahulu, meskipun keutamaan postfiks ++
merupakan yang tertinggi. Pada kasus ini, keutamaan menentukan kepada variabel
apa operator postfiks ++ diterapkan; dengan kata lain, postifks ++ hanya
berperan pada variabel yang ada sebelumnya. Karena alasan ini, ekspresi banyakJeruk+++banyakApel yang telah
dilihat sebelumnya dievaluasi sebagai (banyakJeruk++)
+ banyakApel, bukan banyakJeruk +
(++banyakApel).
Urutan eksekusi
atas operator-operator dengan keutamaan sama pada sebuah statemen ditentukan
dengan apa yang dinamakan dengan asosiatifitas. Operator-operator yang ada pada
baris sama pada tabel di atas memiliki asosiatifitas kiri atau kanan. Operator
dengan asosiatifitas kiri menempel ke operand kirinya. Operator dengan
asosiatifitas kanan menempel ke operand kanannya. Sebagai contoh, jika Anda
menuliskan statemen:
a = b + c + 10;
maka
asosiatifitas kiri yang melekat pada operator + mengimplikasikan bahwa statemen
ini dieksekusi dengan:
a = (b + c) + 10;
Di sisi lain,
operator = dan op= memiliki asosiatifitas kanan, sehingga jika Anda memiliki
variabel int dengan nama a, b, c, dan d yang diinisialisasi dengan 1, maka
statemen:
a += b = c += d = 10;
menetapkan a
menjadi 12, b dan c menjadi 11, dan d menjadi 10. Statemen ini ekivalen dengan:
a += (b = (c += (d = 10)));
2 comments:
Luar biasa, kapan ke mataram?
Minggu depan bro...awal oktober...Bagaimana bro GUI MATLAB untuk pembelajaran dan perkuliahannya...sudah selesai?
Post a Comment