Saturday, September 16, 2017

Kuliah 2 JAVA: Loop & Logika


3. Loop dan Logika




Pada bab ini, Anda akan belajar bagaimana membuat keputusan dan pilihan dalam program-program Java. Anda juga akan belajar bagaimana membuat program Anda mengulangi sejumlah aksi tertentu sampai kondisi spesifik terpenuhi. Pada bab ini, Anda akan belajar:
ð        Bagaimana membandingkan nilai-nilai data
ð        Bagaimana Anda dapat mendefinisikan ekspresi logikal
ð        Bagaimana Anda dapat menggunakan ekspresi logikal untuk mengubah urutan eksekusi statemen
ð        Bagaimana Anda dapat memilih ekspresi tertentu, yang bergantung pada nilai dari ekspresi logikal
ð        Bagaimana memilih opsi tertentu dari sejumlah alternatif yang disediakan
ð        Berapa lama variabel dapat diakses
ð        Bagaimana Anda dapat mengeksekusi secara berulang atau merepetisi sebuah blok kode dengan jumlah repitisi tertentu
ð        Bagaimana Anda dapat merepetisi sebuah blok kode sepanjang ekspresi logikal bernilai true


Membuat Keputusan
Kemampuan membuat keputusan merupakan elemen fundamental pada semua program Java. Anda tentu ingin bisa membuat keputusan seperti, “Jika user ingin memasukkan data lainnya, maka baca nilai tersebut dari papantik” atau “Jika saldo banyak, maka beli mobil sport, kalau tidak beli tiket bus”. Apapun keputusan yang Anda berikan, dalam dunia pemrograman, hal itu terkait dengan kemampuan dalam membuat perbandingan antara variabel, konstanta, dan nilai ekspresi. Jadi, langkah pertama yang penting dipahami dalam membuat keputusan pada sebuah program adalah dengan belajar membuat perbandingan.


Membuat Perbandingan
Java menyediakan enam operator relasional untuk membandingkan dua nilai data. Nilai data yang Anda bandingkan dapat berupa variabel, konstanta, atau ekspresi yang menggunakan nilai-nilai bertipe data primitif seperti byte, short, int, long, char, float, dan double.

Operator Relasional
Penjelasan
> 
Menghasilkan nilai true jika operand kiri lebih besar daripada operand kanan, sebaliknya menghasilkan false.
>=
Menghasilkan nilai true jika operand kiri lebih besar atau sama dengan daripada operand kanan, sebaliknya menghasilkan false.
==
Menghasilkan nilai true jika operand kiri sama dengan operand kanan, sebaliknya menghasilkan false.
!=
Menghasilkan nilai true jika operand kiri tidak sama dengan operand kanan, sebaliknya menghasilkan false.
<=
Menghasilkan nilai true jika operand kiri lebih kecil atau sama dengan operand kanan, sebaliknya menghasilkan false.
< 
Menghasilkan nilai true jika operand kiri lebih kecil daripada operand kanan, sebaliknya menghasilkan false.

Seperti yang Anda lihat, setiap operand menghasilkan nilai true atau false, jadi ini cocok dengan urusan pembuatan keputusan. Ini mengimplikasikan bahwa Anda dapat menggunakan variabel boolean untuk menyimpan hasil perbandingan. Anda telah melihat bagaimana mendeklarasikan variabel bertipe boolean pada bab terdahulu. Misalnya, Anda dapat mendefinisikan sebuah variabel boolean, keadaan, dan menetapkan nilainya menjadi hasil dari sebuah ekspresi yang menggunakan perbandingan berikut:

boolean keadaan = false;          // Mendefinisikan dan menginisialisasi variabel
keadaan = x – y < a + b;          // Menyimpan hasil perbandingan x-y dengan a+b

Nilai dari variabel keadaan akan ditetapkan true pada statemen penugasan jika x – y bernilai kurang dari a + b, dan menjadi false jika tidak.

Untuk memahami bagaimana ekspresi tersebut dievaluasi, lihat kembali tabel keutamaan operator yang telah didiskusikan pada bab sebelumnya. Anda akan melihat bahwa operator-operator perbandingan memiliki keutamaan lebih rendah daripada operator-operator aritmatik, sehingga operator-operator aritmatik akan selalu dieksekusi lebih dahulu daripada operator-operator perbandingan, kecuali jika ada tanda kurung yang mengubah urutan eksekusi. Ekspresi



x – y == a + b

akan memberikan hasli true jika x – y sama dengan a + b, karena sub-subekspresi aritmatik akan dievaluasi lebih dahulu, dan nilai-nilainya akan menjadi operand-operand untuk operator ==. Tentu, Anda bisa menggunakan tanda-kurung, meskipun hal itu tidak akan mengubah hasilnya, tetapi dapat memperjelas makna bagi pembaca:

(x – y) == (a + b)

Perhatikan jika operand kiri dan operand kanan dari operasional relasional memiliki tipe data yang berbeda, maka nilai-nilai akan dipromosi dengan cara sama seperti yang Anda lihat pada bab sebelumnya untuk ekspresi aritmatik campuran atau gabungan. Jadi, jika aDouble merupakan variabel bertipe double dan angka adalah variabel bertipe int pada ekspresi berikut:

aDouble < angka + 1;

maka hasil ekspresi angka + 1 akan dihitung sebagai tipe int, dan nilai ini akan dipromosikan (dikonversi tipe secara implisit) menjadi tipe double sebelum perbandingan dilakukan dengan nilai dari aDouble.

Statemen if
Statemen if, pada konfigurasi sederhananya, memiliki bentuk:

if(ekspresi)
   statemen;

dimana ekspresi dapat berupa sembarang ekspresi yang menghasilkan nilai true atau false. Anda dapat melihat representasi grafikal dari logika ini pada Gambar 3-1.

Gambar 3-1

Jika nilai dari ekspresi bernilai true, maka statemen yang mengikuti if akan dieksekusi, sebaliknya, tidak. Contoh praktisnya diberikan berikut:

if(angka%2 !=0)            // Menguji apakah angka adalah ganjil
  ++angka;           // Jika ya, buat angka menjadi genap

Kondisi if yang diapit tanda-kurung menguji apakah angka bernilai ganjil dengan membandingkan sisa pembagian 2 atas angka dengan 0. Jika sisa tidak sama dengan 0, maka angka bernilai ganjil, jadi 1 akan ditambahkan pada angka. Jika angka bernilai genap, statemen yang menginkremen angka tidak akan dieksekusi.

Anda kadangkala akan melihat sebuah if sederhana yang dituliskan pada satu baris kode. Contoh di atas dapat dituliskan menjadi:

if(angka%2 !=0) ++angka;          // jika angka ganjil, dibuat genap

Hal ini sah dalam Java. Kompilator akan mengabaikan karakter spasi dan baris-baru. Titik-koma berperan sebagai pembatas statemen. Penulisan if dengan cara ini akan menghemat ruang penulisan, dan kadangkala dapat memperjelas pembacaan kode.


Blok Statemen
Anda bisa menciptakan sebuah blok statemen yang diapit dengan simbol kurung-kurawal. Anda bisa menciptakan sebuah blok statemen di dalam statemen if, seperti berikut:

if(ekspresi) {
   statemen 1;
   statemen 2;
   …
   statemen n
}

Sekarang, jika nilai dari ekspresi bernilai true, maka semua statemen yang bersarang di dalam blok tersebut akan dieksekusi. Tentu, tanpa kurung-kurawang, kode tidak lagi memiliki blok statemen:

if(ekspresi)
   statemen 1;
   statemen 2;
   …
   statemen n

Di sini, hanya statemen pertama, statemen 1, yang akan diabaikan jika ekspresi bernilai false; statemen-statemen lain akan selalu dieksekusi tanpa memandang nilai dari ekspresi. Anda dapat melihat dari sini bahwa indentasi (penataan atau pemosisian statemen) hanyalah bantuan visual, yang tidak berpengaruh terhadap bagaimana kode program dieksekusi. Runtun statemen tersebut memang tampak menjadi bagian dari if, tetapi hanya statemen pertama yang menjadi bagian dari if, karena ketiadaan kurung-kurawal.

Sebagai contoh praktis dari statemen if yang memuat sebuah blok statemen, Anda bisa menuliskan:

if(angka%2 != 0) {   // Menguji apakah angka bernilai ganjil
   // jika ya, jadikan genap dan tampilkan pesan
   ++angka;
   System.out.println(“Angka dipaksa menjadi genap dan sekarang “ + angka);
}

Sekarang kedua statemen yang ada di dalam kurung-kurawal akan dieksekusi jika ekspresi dari statemen if bernilai true, dan kedua statemen tersebut tidak akan dieksekusi jika ekspresi bernilai false.

Klausa else
Anda dapat mengembangkan statemen if dasar dengan memanfaatkan klausa else. Ini memberikan statemen atau blok statemen alternatif, yang akan dieksekusi ketika ekspresi pada statemen if bernilai false. Anda dapat melihat sintaksis dari statemen ini, dan bagaimana kendali program mengalir pada Gambar 3-2.

Mekanisme ini memberikan pilihan eksplisit antara dua aksi: satu ketika ekspresi dari statemen if bernilai true; dan lainnya ketika bernilai false.

Anda dapat menerapkannya pada program konsol dan mencoba metode random() dari kelas Math pada saat yang sama.


Latihan
if-else
Ketika Anda telah menuliskan program ini, simpan dan berikan nama PeriksaAngka.java. Kompilasi program tersebut dan jalankan beberapa kali untuk melihat hasilnya.

public class PeriksaAngka {
   public static void main(String[] args) {
      int angka = 0;
      // Mendapatkan sebuah integer acak antara 1 & 100
      angka = 1+(int)(100*Math.random());

      if(angka%2 == 0) { // Menguji apakah genap
         System.out.println("Anda mendapatkan angka genap, " + angka); // genap
      } else {
         System.out.println("Anda mendapatkan angka ganjil, " + angka); // ganjil
      }
   }
}


Gambar 3-2

Penjelasan
Anda telah melihat metode random() yang didefinisikan pada kelas Math pada bab sebelumnya. Metode ini menghasilkan sebuah nilai acak bertipe double antara 0.0 dan 1.0, tetapi hasilnya selalu kurang dari 1.0, jadi nilai terbesar yang mungkin Anda dapatkan adalah 0.9999…. Konsekuensinya, ketika Anda mengalikan nilai yang dihasilkan metode ini dengan 100.0 dan mengkonversi nilai ini menjadi tipe int dengan konversi tipe eksplisit, maka Anda akan membuang bagian pecahannya dan sebuah integer acak antara 0 dan 99 akan dihasilkan. Penambahan 1 menyebabkan integer acak yang dihasilkan menjadi antara 1 dan 100, yang kemudian disimpan pada variabel angka. Anda kemudian menampilkan keluaran pada statemen if. Jika nilai angka adalah genap, maka statemen println() pertama yang akan dieksekusi; sebaliknya, println() kedua pada klausa else yang dieksekusi.


Statemen if Bersarang
Statemen yang dieksekusi ketika ekspresi pada statemen if bernilai true dapat pula berupa statemen if lain. Hal ini berlaku pula pada klausa else. Sebuah statemen if dapat bersarang atau ditempatkan di dalam statemen if lain. Untuk mengilustrasikan statemen if bersarang, Anda perlu memodifikasi if dari contoh sebelumnya:


if(angka%2 == 0) { // Menguji apakah genap
   if(angka < 50) {
      System.out.println("Anda mendapatkan angka genap, " + angka); // genap
   }
} else {
   System.out.println("Anda mendapatkan angka ganjil, " + angka); // ganjil
}

Sekarang pesan untuk nilai genap akan ditampilkan hanya jika nilai dari angka kurang dari 50. Ada tiga kemungkinan yang terjadi pada fragmen kode ini: jika angka bernilai genap dan kurang dari 50, maka Anda akan melihat pesan terkait hal itu; jika angka bernilai genap dan tidak kurang dari 50, maka tidak ada pesan yang ditampilkan; dan terakhir, jika angka bernilai ganjil, maka pesan terkait angka ganjil akan ditampilkan.

Kurung-kurawal yang mengapit if bersarang diperlukan di sini karena adanya klausa else. Kurung-kurawal tersebut mengekang if bersarang. Jika kurung-kurawal tersebut tidak diberikan, program masih dapat dikompilasi, tetapi logika program akan berbeda. Anda akan melihatnya sekarang.

Dengan adanya if bersarang, pertanyaan tentang kepada statemen if manakah klausa else tertentu melekat sering muncul. Jika Anda menghapus kurung-kurawal dari kode di atas, Anda memiliki:

if(angka%2 == 0)  // Menguji apakah genap
   if(angka < 50)
      System.out.println("Anda mendapatkan angka genap, " + angka); // genap
  else
   System.out.println("Anda mendapatkan angka ganjil, " + angka); // ganjil

Ini akan mengubah logika program dari versi sebelumnya, meskipun indentasi (penataan kode) mengimplikasikan sebaliknya. Klausa else sekarang melekat ke if bersarang yang menguji apakah angka bernilai kurang dari 50, jadi pemanggilan println() dieksekusi hanya untuk angka-angka genap yang lebih besar atau sama dengan 50. Ini jelaslah berbeda dengan logika sebelumnya.


Latihan
Mendekripsi Karakter
Ciptakanlah kelas PeriksaHuruf, dan tuliskan kode pada metode main() seperti berikut:

public class PeriksaHuruf {
   public static void main(String[] args) {
      char simbol = 'A';
      // Membangkitkan sebuah karakter acak
      simbol = (char)(128.0*Math.random());
     
      if(simbol >= 'A') { // Apakah huruf A atau lebih besar?
         // ya, apakah kurang dari atau sama dengan Z?
         if(simbol <= 'Z') {
            // Berarti huruf besar
            System.out.println("Anda memiliki huruf besar " + simbol);
         } else { // Tidak kurang dari atau sama dengan Z
            // Apakah sama dengan atau lebih besar dari a?
            if(simbol >= 'a') {
               // Ya, apakah kurang dari atau sama dengan z?
               if(simbol <= 'z') {
                  // Jadi ia adalah huruf kecil
                  System.out.println("Anda memiliki huruf kecil " + simbol);
               } else { // Tidak kurang dari z
                  System.out.println(
                        "Kode lebih besar dari a tetapi bukan huruf");
               }
            } else {
               System.out.println(
                  "Kode kurang dari a dan bukan huruf");
            }
         }
      } else {
         System.out.println("Kode kurang dari A dan bukan huruf");
      }
   }
}

Penjelasan
Program ini mencari-tahu apakah karakter yang disimpan pada variabel simbol adalah huruf besar, huruf kecil, atau karakter lain. Program ini lebih dahulu membangkitkan sebuah karakter acak dengan kode numerik antara 0 dan 127, yang berkaitan dengan karakter-karakter pada himpunan karakter ASCII 7-bit (ISO 646). Pengkodean Unicode untuk karakter-karakter ASCII secara numerik sama dengan nilai-nilai kode ASCII. Pada himpunan karakter ini, huruf ‘A’ sampai ‘Z’ direpresentasikan secara berurutan dengan nilai desimal 65 sampai 90. Huruf-huruf kecil direpresentasikan secara berurutan dengan nilai-nilai kode ASCI yang memiliki nilai desimal 97 sampai 122. Jadi, untuk mengkonversi huruf kecil menjadi huruf besar, Anda perlu menambahkan 32 pada kode karakter.

Statemen-statemen if sedikit sulit dipahami, seperti pada diagam logika pada Gambar 3-3.

Anda memiliki empat statemen if. Statemen if pertama menguji apakah simbol adalah ‘A’ atau lebih besar. Jika ya, ia bisa jadi berupa huruf besar, huruf kecil, atau karakter lain. Tetapi jika tidak, maka ia pasti bukan huruf, jadi klausa else untuk statemen if ini (di akhir program) menghasilkan pesan yang berkaitan dengan itu.

Statemen if bersarang, yang dieksekusi jika simbol adalah ‘A’ atau lebih besar, menguji apakah simbol adalah ‘Z’ atau lebih kecil. Jika ya, maka simbol pasti memuat huruf besar, dan pesan tertentu akan ditampilkan. Jika tidak, maka simbol bisa jadi memuat huruf kecil, jadi statemen if lain dibuat bersarang di dalam klausa else dari statemen if bersarang pertama untuk menguji kemungkinan ini.

Gambar 3-3


Statemen if pada klausa else menguji apakah simbol lebih besar dari ‘a’. Jika tidak, maka Anda mengetahui bahwa simbol bukanlah sebuah huruf, dan sebuah pesan akan ditampilkan. Jika ya, maka if yang lain akan memeriksa apakah simbol adalah ‘z’ atau lebih kecil. Jika ya, maka simbol pastilah sebuah huruf kecil, dan jika tidak, maka ia bukanlah sebuah huruf.


Membandingkan Nilai-Nilai Enumerasi
Anda tidak bisa membandingkan variabel bertipe enumarasi menggunakan operator-operator perbandingan, tetapi Anda bisa melakukannya menggunakan sebuah metode yang disediakan bagi semua objek enumerasi. Dimisalkan bahwa Anda mendefinisikan sebuah tipe enumerasi:

enum Musim {semi, panas, gugur, dingin}

Anda sekarang dapat mendefinisikan dan menginisialisasi sebuah variabel bertipe Musim dengan statemen berikut:

Musim musim = Musim.panas;

Jika nantinya Anda ingin memeriksa apakah yang sedang dimuat di dalam variabel musim, Anda bisa menuliskan:

if(musim.equals(Musim.panas) {
   System.out.println(“Musim panas telah dimulai, rerumputan beranjak hijau.”);
} else {
   System.out.println(“Sekarang belum masuk musim panas!”);
}

Ini akan memanggil metode equals() untuk enumerasi yang diakses oleh musim. Metode ini akan membandingkan nilai pada musim dengan argumen metode dan menghasilkan true apabila keduanya sama atau false jika tidak sama. Anda dapat menggunakan metode equals() untuk membandingkan musim dengan variabel lain bertipe Musim, misalnya:

Musim terbaik = Musim.dingin;     // Sebuah variabel baru diinisialisasi dengan dingin
if(musim.equals(terbaik) {
   System.out.println(“Musim terbaik adalah musim “ + terbaik);
} else {
   System.out.println(“Variabel musim memiliki nilai “ + musim +
                      “ dan variabel terbaik memiliki nilai “ + terbaik);
}

Setelah mendefinisikan variabel terbaik, Anda menguji apakah nilai dari musim sama dengan nilai dari terbaik. Jika ya, statemen keluaran pertama yang dieksekusi. Jika terbaik dan musim bernilai tidak sama, maka statemen keluaran pada blok else yang akan dieksekusi.


Operator-Operator Logikal
Pengujian yang Anda tempatkan pada ekspresi dari statemen if sejauh ini relatif sederhana. Kehidupan nyata umumnya cukup kompleks. Anda akan sering melakukan penggabungan sejumlah kondisi sehingga Anda akan mengeksekusi statemen tertentu, misalnya, jika semua kondisi bernilai true secara bersamaan.

Anda bisa memakai operator-operator logikal untuk menggabungkan sejumlah ekspresi yang memiliki nilai true atau false. Karena setiap operator ini diterapkan pada nilai boolean, maka operator-operator ini juga dikenal sebagai operator boolean. Ada lima operator logikal yang dapat diterapkan pada nilai boolean:

Simbol
Nama Panjang
&
AND logikal
&&
AND kondisional
|
OR logikal
||
OR kondisional
!
Negasi logikal (NOT)

Setiap operator ini cukup sederhana; satu-satunya potensi kebingungan adalah fakta bahwa Anda memiliki dua pilihan operator untuk tiap AND dan OR, yang akan dijelaskan sebentar lagi.


Operasi-Operasi AND Logikal
Anda dapat menggunakan operator AND, && dan &, dimana Anda memiliki dua ekspresi logikal yang harus bernilai true agar hasil bernilai true.  Kedua operator AND tersebut akan memberikan hasil yang sama. Pertama, Anda perlu mengetahui bagaimana keduanya digunakan. Semua diskusi berikut dapat diterapkan pada kedua operator AND tersebut.

Anda akan melihat bagaimana operator logikal dapat menyederhanakan contoh yang terakhir diberikan. Anda dapat menggunakan operator & dan && jika Anda menguji sebuah variabel bertipe char untuk menentukan apakah ia memuat huruf besar atau tidak. Nilai yang sedang diuji harus lebih besar dari atau sama dengan ‘A’ dan kurang dari atau sama dengan ‘Z’. Kedua kondisi harus bernilai true agar nilai adalah sebuah huruf besar. Dengan mengambil contoh dari program sebelumnya, dengan sebuah nilai disimpan pada variabel char, simbol, Anda dapat mengimplementasikan pengujian huruf besar dengan satu if menggunakan operator &&:

if(simbol >= ‘A’ && simbol <= ‘Z’)
   System.out.println(“Anda memiliki huruf besar “ + simbol);

Jika Anda melihat tabel keutamaan operator pada Bab 2, Anda akan mengetahui bahwa operator-operator relasional akan dieksekusi sebelum operator &&, jadi tidak diperlukan tanda kurung di sini. Di sini, statemen keluaran akan dieksekusi hanya jika kedua kondisi yang dikombinasikan oleh operator && bernilai true. Namun, adalah hal baik jika Anda menambahkan tanda-kurung untuk membuat kode lebih mudah dibaca.


Latihan
Mendekripsi Karakter Dengan Mudah
Anda dapat mengganti mekanisme if-else terluar dan isinya pada PeriksaHuruf.java seperti ditampilkan berikut:

public class PeriksaHuruf2 {
   public static void main(String[] args) {
      char simbol = 'A';
     
      // Membangkitkan sebuah karakter acak
      simbol = (char)(128.0*Math.random());

      // Apakah huruf besar?
      if(simbol >= 'A' && simbol <= 'Z') {
         System.out.println("Anda memiliki huruf besar " + simbol);
      } else {
      // Apakah huruf kecil?
         if(simbol >= 'a' && simbol <= 'z') {
            System.out.println("Anda memiliki huruf kecil " + simbol);
         } else { // Kurang dari z
            System.out.println("Kode bukanlah sebuah huruf");
         }
      }
   }
}

Keluaran program sama seperti versi kode sebelumnya.

Penjelasan
Penggunaan operator && cukup memadatkan dan meringkaskan kode. Anda sekarang dapat melakukan pekerjaan ini hanya dengan dua if, dan hal itu lebih mudah untuk dimengerti.

Anda perlu mengetahui bahwa ketika statemen pada klausa else adalah sebuah if, maka statemen if tersebut tersebut dapat ditempatkan pada baris yang sama dengan else, seperti pada:

// Apakah huruf besar?
if(simbol >= 'A' && simbol <= 'Z') {
   System.out.println("Anda memiliki huruf besar " + simbol);
} else if(simbol >= 'a' && simbol <= 'z') {     // Apakah huruf kecil?
    System.out.println("Anda memiliki huruf kecil " + simbol);

} else { // Kurang dari z
      System.out.println("Kode bukanlah sebuah huruf");
}


& versus &&
Jadi, apa perbedaan && dari &? Perbedaaan antara keduanya adalah bahwa kondisional && tidak akan perlu mengevaluasi operand sebelah-kanan apabila operand sebelah-kirinya bernilai false, karena hasilnya sudah pasti bernilai false. Ini akan membuat kode sedikit lebih cepat ketika operand sebelah-kiri bernilai false.

Sebagai contoh, perhatikan statemen-statemen berikut:

int angka = 50;
if(angka<40 && (3*angka – 27)>100) {
   System.out.println(“Angka = “ + angka);
}

Di sini, ekspresi (3*angka – 27)>100 tidak akan pernah dieksekusi karena ekspresi angka<40 selalu bernilai false. Di sisi lain, jika Anda menuliskan statemen sebagai:

int angka = 50;
if(angka<40 & (3*angka – 27)>100) {
   System.out.println(“Angka = “ + angka);
}

Efeknya berbeda. Keseluruhan ekspresi logikal selalu dievaluasi, jadi meskipun operand sisi-kiri dari operator & bernilai false dan hasilnya sudah pasti false, operand sebelah-kiri (3*angka – 27)>100 akan selalu dievaluasi.

Jadi, Anda dapat menggunakan && setiap waktu untuk membuat program Anda sedikit lebih kencang dan melupakan & selamanya? Salah, semua tergantung apa yang sedang Anda lakukan. Hampir pada semua kasus Anda dapat menggunakan &&, tetapi ada beberapa kasus lain ketika Anda ingin memastikan agar operand sebelah-kanan tetap dieksekusi.

Misalnya, terdapat keadaan dimana ekspresi sisi-kanan melibatkan pemodifikasian sebuah variabel, dan Anda menginginkan variabel itu dimodifikasi pada setiap waktu:

if(++nilai%2 == 0 & ++cacah < batas) {
   // Lakukan sesuai
}

Di sini, variabel cacah akan diinkremen setiap waktu. Jika Anda menggunakan && menggantikan &, cacah hanya akan diinkremen jika operand sisi-kiri dari operator AND bernilai true. Anda akan mendapatkan hasil berbeda tergantung dari operator mana yang digunakan.

Perhatikan kasus kedua berikut:

if(cacah > 0 && total/cacah > 5) {
   // Lakukan sesuatu
}

Pada kasus ini, operand sisi-kanan untuk operasi && akan dieksekusi hanya jika operand kiri bernilai true, yaitu ketika cacah bernilai positif. Jelaslah, jika Anda menggunakan & di sini, dan cacah ternyata bernilai 0, maka Anda akan mencoba melakukan pembagian nilai total dengan 0, yang akan menghentikan program.


Operasi-Operasi OR Logikal
Operator OR, | dan ||, dapat diterapkan ketika Anda menginginkan hasil true jika salah satu atau kedua operand bernilai true. OR logikal, ||, memiliki efek mirip seperti pada AND logikal, yaitu mengabaikan evaluasi terhadap operand sisi-kanan ketika operand sisi-kiri bernilai true. Jika operand sisi-kiri bernilai true, hasilnya pasti akan bernilai true tanpa memandang apakah operand sisi-kanan bernilai true atau false.

Ambil sebuah contoh. Sebuah tiket diskon untuk masuk kebun binatang akan diberikan bagi mereka yang berusia di bawah 16 tahun atau bagi mereka yang berusia lebih dari atau sama dengan 65 tahun. Ini dapat diuji menggunakan statemen if berikut:

if(usia < 16 || usia >= 65) {
   hargaTiket = *= 0.9;    // Harga tiket didiskon 10%
}

Efeknya di sini adalah untuk memberikan diskon 10% pada hargaTiket jika salah satu kondisi bernilai true. Jelaslah pada kasus ini, kedua kondisi tidak bisa bernilai true.

Pada operasi | atau ||, Anda akan mendapatkan hasil false hanya jika kedua operand bernilai false. Jika salah satu atau kedua operand bernilai true, maka hasil yang didapatkan adalah true.


Operasi NOT Boolean
Tipe ketiga dari operator logikal, !, diterapkan pada satu operand boolean, dan hasilnya adalah kebalikan dari nilai operand. Jadi, jika nilai dari sebuah variabel boolean, keadaan, bernilai true, maka ekspresi !keadaan memiliki nilai false, dan sebaliknya jika keadaan bernilai false, maka !keadaan akan bernilai true.

if(!(usia >= 16 && usia < 65) {
   hargaTiket = *= 0.9;    // Harga tiket didiskon 10%
}

Ekspresi (usia >= 16 && usia < 65) bernilai true jika usia dari 16 sampai 64. Mereka yang berusia seperti ini tidak akan diberikan diskon, jadi diskon hanya diterapkan ketika ekspresi ini bernilai false. Dengan menerapkan operator ! pada hasil ekspresi ini, Anda dapat mencapai tujuan ini, yaitu mereka yang berusia seperti ini tidak akan diberikan diskon.

Anda juga dapat menerapkan operator ! pada sebuah ekspresi yang merupakan favorit dari Charles Dickens:

!(pendapatan > pengeluaran)

Jika ekspresi ini bernilai true, maka hasilnya adalah kesengsaraan, paling tidak ketika menyita rumah atau barang berharga Anda.

Tentu, Anda dapat mengkombinasikan semua operator logikal, jika diperlukan. Jika sebuah kebun binatang memutuskan untuk memberikan diskon tiket masuk kepada mereka yang berusia di bawah 12 tahun dan dengan tinggi badan 148 cm, atau kepada mereka yang berusia di atas 65 tahun dengan tinggi badan 172 cm, maka Anda dapat menerapkan diskon dengan menerapkan pengujian ini:

if((usia > 12 && tinggi < 148) || (usia > 65 && tinggi >172)) {
   hargaTiket *= 0.8;      // 20 % diskon pada harga tiket
}

Tanda-kurung sebenarnya tidak diperlukan di sini, karena operator && memiliki keutamaan lebih tinggi daripada ||, tetapi penambahan tanda-kurung akan memperjelas bagaimana perbandingan-perbandingan dilakukan.


Pengujian Karakter Menggunakan Metode-Metode Pustaka Standar
Meskipun pengujian karakter menggunakan operator logikal merupakan cara mendemonstrasikan bagaimana operator-operator logikal digunakan, tetapi pada prakteknya ada cara yang lebih mudah. Paket-paket standar Java menyediakan sejumlah metode standar untuk melakukan sejumlah pengujian karakter seperti huruf atau dijit, yang telah Anda lakukan menggunakan statemen if. Semua metode tersebut tersedia pada kelas Character, yang secara otomatis tersedia bagi program Anda. Misalnya, Anda dapat menuliskan statemen if pada program PeriksaHuruf2 seperti ditunjukkan pada contoh berikut:

Latihan
Mendekripsi Karakter Dengan Mudah
Pada contoh berikut, ekspresi-ekspresi if pada main() yang ada pada PeriksaHuruf2 digantikan dengan ekspresi-ekspresi yang memanggil metode-metode pada kelas Character:

import static java.lang.Character.isLowerCase;
import static java.lang.Character.isUpperCase;

public class PeriksaHuruf3 {
   public static void main(String[] args) {
      char simbol = 'A';
      // Membangkitkan sebuah karakter acak
      simbol = (char)(128.0*Math.random());

      if(isUpperCase(simbol)) {
         System.out.println("Anda memiliki huruf besar " + simbol);
      } else {
         if(isLowerCase(simbol)) {
            System.out.println("Anda memiliki huruf kecil " + simbol);
         } else {
            System.out.println("Kode bukan huruf");
         }
      }
   }
}


Penjelasan
Karena Anda memiliki dua statemen import untuk metode isUpperCase dan isLowerCase di awal file sumber, Anda dapat menggunakan kedua metode tersebut tanpa perlu menyebutkan nama kelas Character. Metode isUpperCase() menghasilkan true jika nilai char yang Anda lewatkan kepada metode itu adalah huruf besar, dan false jika tidak. Sama halnya, metode isLowerCase() menghasilkan true jika nilai char yang Anda lewatkan kepada metode itu adalah huruf kecil, dan false jika tidak.

Tabel berikut menunjukkan sejumlah metode lain yang disediakan pada kelas Character yang bisa Anda pakai untuk menguji karakter. Pada tiap kasus, Anda memberikan argumen bertipe char yang akan diuji kepada metode.

Metode
Penjelasan
isDigit()
Menghasilkan true jika argumen adalah sebuah dijit (0 sampai 9), dan false jika tidak.
isLetter()
Menghasilkan true jika argumen adalah sebuah huruf, dan false jika tidak.
isLetterOrDigit()
Menghasilkan true jika argumen adalah huruf atau dijit, dan false jika tidak.
isWhiteSpace()
Menghasilkan true jika argumen adalah spasi putih, dan false jika tidak. Berikut adalah karakter-karakter spasi putih: Space (‘ ‘), Tab (‘\t’), Newline (‘\n’), Carriage Return (‘\r’), Form Feed (‘\f’).


Operator Kondisional
Operator kondisional juga dikenal dengan operator ternary karena ia melibatkan tiga operand. Cara memahaminya lebih baik dengan mempelajari contoh. Dimisalkan bahwa Anda memiliki dua variabel bertipe int dengan nama usiaAnda dan usiaSaya, dan Anda ingin menugaskan nilai terbesar dari nilai-nilai tersimpan pada usiaAnda dan usiaSaya ke dalam variabel ketiga, lebihTua, yang juga bertipe int. Anda dapat melakukannya dengan statemen berikut:

lebihTua = usiaAnda > usiaSaya ? usiaAnda : usiaSaya;

Operator kondisional memiliki sebuah ekspresi logika sebagai operand pertamanya. Pada kasus ini, operand pertamanya adalah usiaAnda > usiaSaya. Jika ekspresi ini bernilai true, maka operand yang ada setelah simbol ?, pada kasus ini usiaAnda, akan dievaluasi untuk memberkan hasil dari operasi. Jika ekspresi usiaAnda > usiaSaya bernilai false, maka operand ketiga yang ada setelah simbol :, pada kasus ini usiaSaya, akan dievaluasi menjadi hasil dari operasi. Nilai hasil kemudian disimpan pada variabel lebihTua. Kegunaan dari operator kondisional pada statemen penugasan ini ekivalen dengan statemen if:

if(usiaAnda > usiaSaya) {
   lebihTua = usiaAnda;
} else {
   lebihTua = usiaSaya;
}

Ingat, meskipun operator kondisional adalah sebuah operator, bukan statemen, Anda dapat menggunakannya pada sebuah ekspresi yang lebih kompleks yang melibatkan operator-operator lain. Operator kondisional dapat digeneralisir menjadi:

ekspresi_logikal ? ekspresi1: ekspresi2;

Jika ekspresi_logikal dievaluasi true, hasil operasi adalah nilai dari ekspresi1, dan jika ekspresi_logikal dievaluasi false, hasilnya adalah nilai dari ekspresi2.


Latihan
Kondisional
Ketiklah kode berikut, yang menambahkan ‘topi’ di akhir kalimat tergantung dari berapa banya topi yang Anda miliki:

public class OperatorKondisional {
   public static void main(String[] args) {
      int nTopi = 1; // Banyak topi

      System.out.println("Saya memiliki " + nTopi + " topi" + (nTopi == 1 ? "." : "-topi."));

      nTopi++; // Menginkremen banyak topi
      System.out.println("Saya memiliki " + nTopi + " topi" + (nTopi == 1 ? "." : "-topi."));
   }
}

Keluaran program:

Saya memiliki 1 topi.
Saya memiliki 2 topi-topi.

Penjelasan
Hasil eksekusi atas operator kondisional pada program di atas adalah sebuah string yang memuat sebuah titik ketika nilai dari nTopi adalah 1, atau sebuah string yang memuat “-topi.” untuk kasus-kasus lain. Efeknya adalah menyebabkan statemen keluaran untuk secara otomatis mengubah keluaran antara singular dan plural.




Statemen switch
Anda menggunakan statemen switch untuk memilih salah satu dari sejumlah pilihan berdasarkan nilai ekspresi. Ekspresi harus menghasilkan sebuah nilai bertipe integer selain long atau sebuah nilai bertipe enumerasi. Jadi, ekspresi yang mengendalikan statemen switch dapat menghasilkan sebuah nilai bertipe char, byte, short, int, atau konstanta enumerasi.

Berikut adalah salah satu contoh statemen switch:

switch(cuci) {
   case 1:                 // cuci bernilai 1 untuk Katun
      System.out.println(“Katun dipilih”);
      break;
   case 2:                 // cuci bernilai 2 untuk Linen
      System.out.println(“Linen dipilih”);
      break;
   case 3:                 // cuci bernilai 3 untuk Wol
      System.out.println(“Wol dipilih”);
      break;
   default:          // cuci tidak valid
      System.out.println(“Error pemilihan”);
      break;
}

Pemilihan pada statemen switch ditentukan oleh nilai ekspresi yang ditempatkan di dalam kurung, yang ada setelah katakunci switch. Pada kasus ini, ekspresi merupakan sebuah variabel cuci yang perlu dideklarasikan sebagai tipe char, byte, short, atau int. Anda mendefinisikan opsi-opsi switch dengan satu atau lebih kasus, menggunakan katakunci case. Umumnya, tiap kasus memuat katakunci case yang diikuti dengan sebuah nilai konstan yang merupakan nilai penentu kasus, yang diikuti dengan simbol titik-dua. Statemen-statemen akan dieksekusi ketika kasus tertentu dipilih berdasarkan nilai ekspresi. Pada contoh ini, Anda memiliki tiga kasus, ditambah dengan kasus spesial dengan label default. Kasus spesial ini dipilih jika nilai dari ekspresi switch (pada kasus ini, cuci) tidak cocok dengan nilai-nilai konstan kasus.

Ketika kasus tertentu dipilih, statemen-statemen yang ada setelah label kasus akan dieksekusi. Jadi, jika cuci bernilai 2, maka statemen-statemen yang ada setelah case 2 akan dieksekusi: Pada kasus ini, statemen-statemen tersebut adalah:

System.out.println(“Linen dipilih”);
break;

Ketika statemen break dieksekusi, hal itu menyebabkan eksekusi berlanjut ke statemen yang ada setelah kurung kurawal penutup switch, }. Statemen break tidak harus menjadi statemen terakhir untuk tiap kasus, tetapi jika Anda tidak menempatkan statemen break di akhir statemen-statemen pada sebuah kasus, maka statemen-statemen yang ada pada kasus berikutnya akan dieksekusi pula. Statemen break pada kasus default sebenarnya tidak diperlukan.

Anda bisa menuliskan ulang statemen switch sebelumnya dengan memanfaatkan sebuah variabel bertipe enumerasi sebagai ekspresi pengendali statemen switch. Dimisalkan Anda telah mendefinisikan tipe enumerasi PilihanCuci seperti ini:

enum PilihanCuci {katun, linen, wol}     // Mendefinisikan tipe enumerasi

Anda sekarang dapat menuliskan statemen switch seperti ini:

PilihanCuci cuci = PilihanCuci.linen;    // Definisi awal untuk variabel cuci

switch(cuci) {
   case katun:                    // cuci bernilai 1 untuk Katun
      System.out.println(“Katun dipilih”);
      break;
   case linen:       // cuci bernilai 2 untuk Linen
      System.out.println(“Linen dipilih”);
      break;
   case wol:         // cuci bernilai 3 untuk Wol
      System.out.println(“Wol dipilih”);
      break;
   default:          // cuci tidak valid
      System.out.println(“Error pemilihan”);
      break;
}

Statemen switch dikendalikan oleh nilai dari variabel cuci. Perhatikan bagaimana Anda menggunakan konstanta enumerasi sebagai nilai kasus. Anda perlu menuliskannya tanpa menyebutkan nama tipe enumerasi sebagai konstanta kasus. Pada kasus ini, Anda menggunakan case katun, bukan case PilihanCuci.katun.


Generalisasi Statemen switch
Logikal dari statemen switch ditampilkan pada diagram alir pada Gambar 3-4.

Gambar 3-4

Setiap nilai kasus dibandingkan dengan nilai dari ekspresi. Jika salah satu cocok atau sama, maka kode yang ada pada kasus itu akan dieksekusi, dan statemen break menyebabkan aliran eksekusi melompat ke statemen pertama yang ada setelah switch. Jika Anda tidak mencantumkan statemen break, maka logika program menjadi berbeda, seperti ditunjukkan pada Gambar 3-5.

Sekarang ketika sebuah nilai label kasus sama dengan ekspresi switch, kode untuk kasus itu akan dieksekusi, dan statemen-statemen untuk semua kasus yang ada setelahnya juga akan dieksekusi, termasuk kasus default.

Gambar 3-5

Anda dapat mengeksekusi statemen-statemen yang sama untuk kasus-kasus berbeda, seperti pada statemen switch berikut:

char yaTidak = ‘T’;
// logikal program lain…

switch(yaTidak) {
case ‘t’: case ‘T’:
   System.out.println(“Tidak yang diseleksi”);
   break;
case ‘y’: case ‘Y’:
   System.out.println(“Ya yang diseleksi”);
   break;
}

Di sini, variabel yaTidak menerima sebuah karakter dari keyboard. Anda menginginkan aksi berbeda tergantung dari apakah user memasukkan ‘Y’ atau ‘T’, tetapi Anda menginginkan agar program dapat menerima huruf besar maupun huruf kecil dari user. Statemen switch ini melakukannya dengan menempatkan label-label kasus bersamaan. Perhatikan bahwa tidak ada kasus default di sini. Jika yaTidak memuat sebuah karakter selain yang diidentifikasi pada statemen-statemen kasus, statemen switch tidak memiliki efek apapun. Pada prakteknya, Anda menambahkan kasus default pada kasus ini untuk menampilkan sebuah pesan yang mengindikasikan bahwa nilai yaTidak tidak valid.

Tentu, Anda juga dapat mengimplementasikan logika ini menggunakan statemen-statemen if:

if(yaTidak == ‘t’ || yaTidak == ‘T’) {
   System.out.println(“Tidak yang diseleksi”);
} else {
   if(yaTidak == ‘y’ || yaTidak == ‘Y’) {
      System.out.println(“Ya yang diseleksi”);
   }
}


Latihan
Menggunakan Statemen switch
Contoh ini menggunakan sebuah statemen switch yang dikendalikan oleh suatu variabel bertipe integer dan sebuah statemen switch yang dikendalikan oleh suatu variabel bertipe enumerasi:

public class CobaSwitch {
       // Mendefinisikan tipe enumerasi
   enum PilihanCuci {katun, linen, wol, sintetis}

   public static void main(String[] args) {
      // Variabel untuk medefinisikan pilihan cuci
      PilihanCuci cuci = PilihanCuci.katun;
     
      // Variabel cuci menetapkan jenis pakaian yang dicuci
      // menggunakan nilai integer:
      // 1:kemeja 2:sweater 3:kaus kaki 4:sepatu 5:celana
      int pakaian = 3;
      switch(pakaian) {
         case 1:
            System.out.println("Mencuci kemeja.");
            cuci = PilihanCuci.katun;
            break;
         case 2:
            System.out.println("Mencuci sweater.");
            cuci = PilihanCuci.wol;
            break;
         case 3:
            System.out.println("Mencuci kaus-kaki.");
            cuci = PilihanCuci.wol;
            break;
         case 4:
            System.out.println("Mencuci sepatu.");
            cuci = PilihanCuci.linen;
            break;
         case 5:
            System.out.println("Mencuci celana.");
            cuci = PilihanCuci.sintetis;
            break;
         default:
            System.out.println("Mencuci tak dikenal - default sintetis.");
            cuci = PilihanCuci.sintetis;
            break;
      }

      // Sekarang memilih suhu pencucian
      System.out.println("Sedang mencuci "+ cuci);
      switch(cuci) {
         case wol:
            System.out.println("Suhu pencucian 20 derajat Celcius.");
            break;
         case katun:
            System.out.println("Suhu pencucian 70 derajat Celcius.");
            break;
         case sintetis:
            System.out.println("Suhu pencucian 30 derajat Celcius.");
            break;
         case linen:
            System.out.println("Suhu pencucian 80 derajat Celcius.");
            break;
      }
   }
}

Keluaran program:

Mencuci kaus-kaki.
Sedang mencuci wol
Suhu pencucian 20 derajat Celcius.


Penjelasan
Kode ini tampak panjang, karena adanya sejumlah kasus pada dua statemen switch. Anda lebih dahulu mendefinisikan sebuah tipe enumerasi, PilihanCuci. Anda kemudian mendefinisikan sebuah variabel bertipe enumerasi ini pada metode main() dengan statemen berikut:

PilihanCuci cuci = PilihanCuci.katun;

Nilai awal untuk cuci di sini dapat diubah menjadi konstanta bertipe enumerasi PilihanCuci yang lain. Selanjutnya, Anda mendefinisikan dan menginisialisasi sebuah variabel yang mengidentifikasi tipe pakaian yang dicuci:

// Variabel cuci menetapkan jenis pakaian yang dicuci
// menggunakan nilai integer:
// 1:kemeja 2:sweater 3:kaus kaki 4:sepatu 5:celana
int pakaian = 3;

Nilai awal untuk variabel pakaian berkaitan dengan kaus kaki. Anda menggunakan variabel pakaian untuk mengendalikan statemen switch dengan ekspresi pengendali pakaian. Untuk setiap kasus pada switch ini, Anda menampilkan apa yang sedang dicuci dan menetapkan nilai variabel cuci menjadi konstanta enumerasi tertentu. Anda menempatkan sebuah kasus default pada statemen switch ini karena ekspresi pengendalinya adalah nilai numerik. Jika tidak ada kasus default dan ekspresi pengendali swicth menghasilkan sebuah nilai yang tidak sama dengan semua kasus yang ada, maka aliran eksekusi akan berlanjut ke statemen yang ada setelah blok switch.

Setelah switch pertama, Anda menampilkan apa yang sedang dicuci:

System.out.println("Sedang mencuci "+ cuci);

Anda telah melihat pada bab sebelumnya bahwa representasi string atas sebuah nilai yang merupakan konstanta enumerasi adalah nama nilai seperti pada definisi tipe.

Terakhir, Anda menggunakan variabel cuci sebagai ekspresi untuk memilih sebuah kasus pada statemen switch berikutnya. Karena variabel bertipe enumerasi harus memiliki konstanta enumerasi sebagai nilai, dan semua nilai yang mungkin direpresentasikan oleh kasus-kasus pada switch, maka Anda tidak memerlukan kasus default di sini.

Perhatikan bahwa Anda bisa saja mendefinisikan nilai dari tiap pakaian sebagai nilai konstanta seperti berikut:

final int KEMEJA = 1;
final int SWEATER = 2;
final int KAUSKAKI = 3;
final int SEPATU = 4;
final int CELANA = 5;

Nilai untuk variabel pakaian kemudian dapat ditetapkan berikut:

int pakaian = KAUSKAKI;

Tentu, Anda bisa juga menggunakan enumerasi untuk tipe pakaian, tetapi hal itu biarlah menjadi tugas Anda.


Skop Variabel
Skop atas sebuah variabel merupakan bagian program dimana nama variabel dapat diakses atau dikenali. Setiap variabel yang telah dideklarasikan sejauh ini pada contoh-contoh program telah didefinisikan di dalam sebuah metode main(). Setiap variabel yang didefinisikan di dalam sebuah metode disebut dengan variabel lokal, karena hanya dapat dieakses di dalam metode dimana variabel tersebut didefinisikan. Lihat fragmen kode berikut, yang menunjukkan varibel-variabel yang didefinisikan pada blok-blok bersarang:

{
int n = 1;

// Mengakses n dapat dilakukan di sini

// Mengakses m di sini mengakibatkan error karena m belum ada

   {
      // Mengakses n juga bisa dilakukan di sini
      // Mengakses m di sini masih menyebabkan error

      int m = 2;     // Mendeklarasikan dan mendefinisikan m

      // Mengakses m dan n di sini bisa dilakukan, keduanya eksis
   }  // m lenyap di titik ini

   // Mengakses m akan menyebabkan error di sini
   // Mengakses n dapat juga dilakukan di sini
}
// n tidak bisa lagi diakses di sini

Sebuah variabel tidak bisa diakses sebelum dideklarasikan; Anda hanya bisa mengaksesnya hanya ketika variabel dideklarasikan. Variabel itu tetap dapat diakses sampai akhir blok di mana ia didefinisikan, dan itu termasuk semua blok yang bersarang di dalam blok pemuat variabel tersebut. Variabel n diciptakan pada statemen pertama pada blok terluar. Variabel itu tetap ada dan bisa diakses di dalam blok yang bersarang di dalam blok terluar. Variabel m hanya ada dan bisa diakses di dalam blok bersarang karena di sana lah variabel itu dideklarasikan. Setelah kurung-kurawal penutup di akhir blok bersarang, m tidak lagi ada dan tidak lagi bisa diakses. Variabel n masih tetap ada dan bisa diakses sampai kurung-kurawal penutup dari blok terluar.

Jadi, aturan yang menentukan aksesibilitas dari variabel lokal cukup sederhana. Variabel lokal hanya dapat diakses dari titik pada program dimana variabel itu dideklarasikan sampai akhir blok yang memuat pendeklarasian tersebut. Di akhir blok dimana variabel lokal dideklarasikan, variabel itu tidak lagi bisa diakses. Hal ini didemonstrasikan pada contoh berikut:

Latihan
Skop Variabel
Berikut adalah sebuah versi dari metode main() yang mendemonstrasikan bagaimana skop variabel diterapkan dalam Java:

public class SkopVariabel {
   public static void main(String[] args) {
      int terluar = 1; // Exists throughout the method
     
      {
         // Anda tidak bisa mengakses sebuah variabel sebelum dideklarasikan
         // Hapus ini akan terjadi error
         // System.out.println("terdalam = " + terdalam);

         int terdalam = 2;
         System.out.println("terdalam = " + terdalam); // OK dilakukan
        
         // dan terdalam masih dapat diakses di sini
         System.out.println("terluar = " + terluar);

         // Semua variabel yang didefinisikan pada blok terluar masih
         // dapat diakses di sini,
         // jadi Anda tidak bisa melakukan pendefinisian-ulang
        
         // Hapus ini akan terjadi error
         / int terluar = 5;
      }

      // Semua variabel yang dideklarasikan pada blok terdalam tidak lagi ada
      // Jadi Anda tidak bisa mengaksesnya di sini
     
      // Hapus ini akan terjadi error
      // System.out.println("terdalam = " + terdalam);
     
      // Variabel yang didefinisikan pada blok terdalam
      // tidak lagi ada, jadi Anda bisa mendefiniskannya ulang
      int terdalam = 3;
      System.out.println("terdalam = " + terdalam); // ... menampilkan nilainya
      System.out.println("terluar = " + terluar);   // terluar masih tetap ada
   }
}

Keluaran program:

terdalam = 2
terluar = 1
terdalam = 3
terluar = 1

Jika Anda menghapus salah satu atau ketiga statemen yang diperingatkan, maka program tidak akan bisa dikompilasi:

--------------------Configuration: SkopVariabel - JDK version 1.8.0_131 <Default>
SkopVariabel.java:8: error: cannot find symbol
         System.out.println("terdalam = " + terdalam);
                                            ^
  symbol:   variable terdalam
  location: class SkopVariabel
SkopVariabel.java:21: error: variable terluar is already defined in method main(String[])
          int terluar = 5;
              ^
SkopVariabel.java:28: error: cannot find symbol
       System.out.println("terdalam = " + terdalam);
                                          ^
  symbol:   variable terdalam
  location: class SkopVariabel
3 errors

Penjelasan
Metode main() pada program ini memiliki satu blok yang bersarang di dalam blok pemuat kode untuk metode ini. Variabel terluar didefinisikan tepat di awal metode main(), jadi Anda dapat mengaksesnya di mana saja di dalam metode main(), termasuk di dalam blok bersarang. Anda tidak dibolehkan mendefinisikan ulang sebuah variabel, jadi bila Anda mengaktifkan komentar yang mendefinisikan ulang terluar di dalam blok bersarang, hal itu akan menyebabkan error kompilasi.

Variabel terdalam didefinisikan di dalam blok bersarang dengan nilai awal 2, dan Anda dapat mengaksesnya di mana saja dimulai dari titik pendeklarasiannya sampai akhir blok bersarang. Setelah kurung-kurawal penutup dari blok bersarang, variabel terdalam tidak lagi ada, jadi bila Anda mengaktifkan statemen yang mengakses terdalam pada titik itu, hal itu akan menyebabkan error kompilasi. Namun, karena variabel terdalam tidak lagi ada, Anda dapat mendeklarasikan variabel lain dengan nama sama dengan nilai awal 3.

Perhatikan bahwa ini hanya diperuntukkan untuk mendemonstrasikan bagaimana masa-hidup dari variabel lokal diperlakukan. Anda tidak direkomendasikan mendefinisikan-ulang variabel lokal yang telah habis masa-hidupnya, karena hal itu berpotensi memicu kebingungan pembaca program.



Loop
Sebuah loop dapat dipakai untuk mengeksekusi sebuah statemen atau blok statemen secara berulang. Kebutuhan akan eksekusi berulang atas sebuah blok kode seringkali dijumpai pada sebuah program. Perhatikan contoh program berikut:

public class CobaContoh1 {
   public static void main(String[] args) {
      int nilai = 1;
     
      nilai *= 2;
      System.out.println("Nilai sekarang adalah "+nilai);

      nilai *= 2;
      System.out.println("Nilai sekarang adalah "+nilai);

      nilai *= 2;
      System.out.println("Nilai sekarang adalah "+nilai);

      nilai *= 2;
      System.out.println("Nilai sekarang adalah "+nilai);

      nilai *= 2;
      System.out.println("Nilai sekarang adalah "+nilai);

      nilai *= 2;
      System.out.println("Nilai sekarang adalah "+nilai);

      nilai *= 2;
      System.out.println("Nilai sekarang adalah "+nilai);

      nilai *= 2;
      System.out.println("Nilai sekarang adalah "+nilai);
   }
}

Pasangan-pasangan statemen yang sama dimasukkan delapan kali. Ini merupakan cara melelahkan dalam melakukan sesuatu. Jika program dipakai untuk menghitung tiap karyawan dengan total 1000 karyawan, maka panjang program akan beratus-ratus halaman hanya untuk melakukan pekerjaan yang sama. Anda bisa menuliskan program di atas untuk melakukan pekerjaan sama seperti berikut:

public class CobaContoh1_1 {
   public static void main(String[] args) {
      int nilai = 1;
      
      for (int i=0; i<8 ; i++) {
         nilai *= 2;
         System.out.println("Nilai sekarang adalah "+nilai);
      }
   }
}

Ini merupakan salah satu jenis loop, yang dikenal sebagai loop for. Statemen loop for di baris keempat menyebabkan statemen-statemen pada blok loop for dieksekusi delapan kali. Banyak eksekusi yang akan diulangi ditentukan oleh  kendali yang diapit di dalam kurung setelah katakunci for. Anda akan mempelajarinya sebentar lagi. Tujuan utama dari loop for adalah mengeksekusi sebuah blok statemen secara berulang, sesuai dengan yang ditetapkan.

Secara umum, sebuah loop memiliki dua bagian: tubuh loop, yang merupakan sebuah statemen atau blok statemen yang mendefinisikan kode yang akan dieksekusi secara berulang; mekanisme kendali loop yang menentukan berapa kali eksekusi akan diulangi.


Varietas Loop
Ada empat jenis loop yang dapat digunakan:
1.      Loop for numeris:

for (ekspresi_inisialisasi; kondisi_loop; ekspresi_inkremen) {
   // statemen-statemen
}

Loop for numeris umumnya dinamakan sebagai loop for saja. Tubuh loop ini adalah blok statemen yang diapit oleh kurung-kurawal. Blok statemen ini bisa saja berupa sebuah statemen, dimana pada kasus ini kurung-kurawal menjadi opsional. Kode untuk mengendalikan loop for ditempatkan di dalam kurung, yang ada setelah katakunci for. Seperti yang dapat Anda lihat, mekanisme kendali loop memiliki tiga bagian, yang dipisahkan dengan titik-koma. Bagian pertama, ekspresi_inisialisasi, dieksekusi sebelum loop diawali. Anda umumnya menggunakan ekspresi ini untuk menginisialisasi sebuah pencacah untuk banyak iterasi loop, misalnya, i = 0. Dengan sebuah loop dikendalikan oleh pencacah, yang dapat berupa variabel integer atau variabel titik-mengambang, Anda dapat mencacah naik atau turuh dengan inkremen atau dekremen sampai variabel mencapai batas yang didefinisikan.

Eksekusi atas loop ini berlanjut sepanjang kondisi yang Anda tetapkan pada bagian kedua dari mekanisme kendali, kondisi_loop, bernilai true. Ekspresi ini diperiksa di awal dari tiap iterasi loop, dan sepanjang bernilai true, tubuh loop akan tetap dieksekusi. Ketika kondisi_loop bernilai false, loop akan berakhir dan eksekusi dilanjutkan ke statemen yang ada setelah blok loop. Misalnya, jika Anda menggunakan i < 10 sebagai ekspresi kondisi_loop, maka loop akan tetap dieksekusi sepanjang variabel i memiliki nilai kurang dari 10. Bagian ketiga dari mekanisme kendali, ekspresi_inkremen, umumnya dipakai untuk menginkremen pencacah loop. Ini akan dieksekusi di akhir dari tiap iterasi loop. Ekspresi ini dapat berupa i++, yang akan menginkremen pencacah loop, i, sebesar 1. Tentu, Anda dapat menginkremen pencacah loop dengan langkah lebih besar dari 1. Misalnya, Anda bisa saja menuliskan i += 2 sebagai ekspresi_inkremen untuk menginkremen pencacah loop sebesar 2, atau bahkan Anda bisa juga menggunakan, misalnya, i = 2*i + 1, sebagai ekspresi_inkremen.

2.      Loop for berbasis koleksi:

for (tipe_data pengenal : ekspresi_iterasi) {
   // statemen-statemen
}

Anda tidak akan bisa memapahami kapabilitas loop ini sampai Anda mempelajari Collection, jadi Anda akan diberikan penjelasan singkat saja tentang loop ini. Loop for ini memiliki dua elemen kendali yang dipisahkan oleh titik-dua yang ada di dalam kurung setelah katakunci for. Elemen pertama adalah pengenal dengan tipe data yang Anda tetapkan, dan elemen kedua adalah sebuah ekspresi yang menetapkan koleksi objek atau nilai yang ada pada koleksi, dan Anda dapat mengakses item pada tubuh loop menggunakan pengenal. Anda dapat menerapkan bentuk loop for ini untuk array maupun untuk koleksi.

3.      Loop while:

while (ekspresi) {
   // statemen-statemen
}

Loop ini dieksekusi sepanjang ekspresi logis yang diapit tanda-kurung bernilai true. Ketika ekspresi bernilai false, maka loop loop akan berakhir dan eksekusi dilanjutkan pada statemen yang ada setelah blok loop. Ekspresi ini diuji di awal loop, jadi jika awalnya bernilai false, maka tubuh loop tidak akan dieksekusi sama sekali. Salah satu contoh dari kondisi loop while adalah yaTidak == ‘Y’ || yaTidak == ‘y’. Ekspresi ini akan bernilai true jika varaibel yaTidak memuat ‘y’ atau ‘Y’.

4.      Loop do while:

do {
   // statemen-statemen
} while (ekspresi);

Loop ini mirip dengan loop while, kecuali bahwa ekspresi pengendali loop diuji di akhir blok loop. Ini berarti bahwa tubuh loop akan selalu dieksekusi sedikitnya satu kali eksekusi, bahkan jika ekspresi selalu bernilai false.


Logika dasar dari keempat jenis loop ditunjukkan pada Gambar 3-6.

Gambar 3-6

Dua versi loop memiliki mekanisme pengendali berbeda dalam mengendalikan banyak iterasi. Anda dapat pula melihat cukup jelas bahwa perbedaan utama antara loop while dan loop do while adalah tempat di mana pengujian dilakukan.

Latihan
Loop for Numerik
Akan diawali dengan contoh yang sangat sederhana. Dimisalkan bahwa Anda ingin menghitung penjumlahan atas integer-integer dari 1 sampai nilai tertentu yang diberikan. Anda dapat melakukan ini menggunakan loop for seperti pada contoh berikut:

public class LoopFor {
   public static void main(String[] args) {
      int limit = 20; // Penjumlahan dari 1 sampai nilai ini
     
      // Penjumlahan akumulasi disimpan pada variabel ini
      int sum = 0;

      // Loop dari 1 sampai nilai dari limit
      for(int i = 1; i <= limit; i++) {
         sum += i; // Menjumlahkan nilai terkini dari i pada sum
      }

      System.out.println("sum = " + sum);
   }
}

Keluaran program:

sum = 210

Anda bisa mencoba nilai berbeda untuk limit untuk mendapatkan hasil berbeda.

Penjelasan
Pencacah loop adalah i, dan ia dideklarasikan dan diinisialisasi di dalam statemen loop for. Sintaksis untuk loop for ini ditunjukkan pada Gambar 3-7.

Seperti yang Anda lihat, ada tiga elemen pengendali operasi loop for, dan ketiganya ada di dalam kurung yang ada setelah katakunci for. Secara berurutan, tujuan ketiga elemen pengendali tersebut adalah untuk:
ð        Menetapkan kondisi-kondisi awal loop, khususnya pencacah loop
ð        Menetapkan kondisi untuk menentu kelanjutan eksekusi loop
ð        Menginkremen pencacah loop

Ketiga elemen pengendali loop dipisahkan oleh titik-koma. Elemen pengendali pertama dieksekusi ketika loop pertama kali dieksekusi. Di sini, Anda mendeklarasikan dan menginisialisasi pencacah loop, i. Karena pencacah loop dideklarasikan di dalam loop, variabel i tidak dikenali di luar loop. Jika Anda mencoba menampilkan nilai i di luar loop dengan statemen seperti:

System.out.println(“Nilai akhir i = “ + i);     // Tidak akan bisa dikompilasi

Anda akan menjumpai bahwa program tidak akan bisa dikompilasi.

Ketika tubuh loop hanya memuat satu statemen, Anda dapat mengabaikan kurung-kurawal dan menuliskan loop seperti ini:

for (int i = 1; i <= limit; i++)
   sum += i;  // Menambahkan nilai terkini dari i pada sum

Tetapi, Anda direkomendasikan untuk tetap menggunakan kurung-kurawal untuk memperjelas di mana tubuh loop berakhir.

Gambar 3-7


Jika Anda perlu menginisialisasi dan/atau mendeklarasikan variabel-variabel lain untuk loop, Anda dapat melakukannya di sini dengan memisahkan deklarasi-deklarasi dengan koma. Misalnya, Anda dapat menuliskan:

for (int i = 1, j = 0; i <= limit; i++) {
   sum += i * j++;   // Menambahkan nilai terkini dari i*j pada sum
}

Pada fragmen kode ini, variabel j diinisialisasi. Perhatikan bahwa j akan diinkremen setelah hasil dari i * j selesai dihitung. Anda dapat mendeklarasikan variabel-variabel lain di situ.

Elemen pengendali kedua pada sebuah loop for adalah sebuah ekspresi logikal yang diperiksa di awal dari tiap iterasi loop. Jika ekspresi bernilai true, maka loop akan berlanjut, tubuh loop akan dieksekusi, dan ketika ekspresi bernilai false, tubuh loop tidak lagi dieksekusi. Pada contoh program, loop berakhir ketika i lebih besar dari nilai dari limit.

Elemen pengendali ketiga pada sebuah loop for umumnya menginkremen variabel loop, seperti yang telah Anda lihat pada contoh. Anda dapat menempatkan beberapa ekspresi di sini. Misalnya, Anda dapat menuliskan kembali fragmen kode sebelumnya dengan menambahkan j pada loop:

for (int i = 1, j = 0; i <= limit; i++, j++) {
   sum += i * j++;   // Menambahkan nilai terkini dari i*j pada sum
}

Lagi, bisa ditempatkan beberapa ekspresi di sini, meskipun tidak berkorelasi secara langsung dengan kendali loop. Anda dapat menuliskan ulang loop semula untuk menjumlahkan integer-integer sehingga penjumlahan terjadi pada elemen kendali loop:

for (int i = 1; i <= limit; sum += i, i++) {
   ;
}

Sekarang, statemen loop kosong, jadi Anda hanya perlu titik-koma untuk menghentikannya. Versi kode ini memang tidak mudah untuk dipahami pembaca program dan ada bahayanya bila menuliskan loop dengan cara ini. Jika Anda ingin membalikkan urutan penjumlahan pada sum dan penginkremenan i sebagai berikut:

for (int i = 1; i <= limit; i++, sum += i) { // Salah!!
   ;
}

maka Anda akan mendapatkan jawaban yang salah. Ini karena ekspresi i++ akan dieksekusi sebelum sum += j dieksekusi. Jadi nilai salah dari i yang digunakan.

Anda dapat mengabaikan satu atau semua elemen yang mengendalikan loop for, tetapi Anda perlu mencantumkan titik-koma. Adalah tugas Anda untuk memastikan bahwa loop melakukan apa yang Anda minta. Anda bisa menuliskan ulang loop pada program menjadi berikut:

for (int i = 1; i <= limit;) {
   sum += i++;       // Menambahkan nilai terkini dari i pada sum
}


Mencacah Menggunakan Nilai-Nilai Titik-Mengambang
Anda bisa menggunakan variabel titik-mengambang sebagai pencacah loop jika diperlukan. Ini diperlukan ketika Anda sedang menghitung nilai dari sebuah fungsi untuk suatu rentang nilai pecahan. Dimisalkan bahwa Anda ingin menghitung luas lingkaran dengan nilai radius dari 1 sampai 2 dengan langkah 0.2. Anda dapat menuliskannya seperti ini:

for (double radius = 1.0; radius <= 2.0; radius += 0.2) {
   System.out.println(“radius = “ + radius + “ luas = “ + Math.PI*radius*radius);
}

Ini akan menghasilkan keluaran:

radius = 1.0 luas = 3.141592653589793
radius = 1.2 luas = 4.523893421169302
radius = 1.4 luas = 6.157521601035994
radius = 1.5999999999999999 luas = 8.04247719318987
radius = 1.7999999999999998 luas = 10.178760197630927
radius = 1.9999999999999998 luas = 12.566370614359169

Luas telah dihitung menggunakan formula ( dengan nilai standar PI yang didefinisikan pada kelas Math). Meskipun Anda bermaksud untuk mencacah nilai radius dari 1.0 sampai 2.0 dengan inkremen 0.2, tetapi tampaknya hal itu tidak berhasil dilakukan. Nilai radius tidak pernah sampai persis 2.0 atau nilai-nilai lainnya karena 0.2 tidak dapat secara eksak direpresentasikan sebagai sebuah nilai titik-mengambang biner. Jika Anda meragukannya, bersiaplah untuk menangani sebuah loop tak-hingg bila mengubah loop tersebut menjadi:

for (double radius = 1.0; radius != 2.0; radius += 0.2) {
   System.out.println(“radius = “ + radius + “ luas = “ + Math.PI*radius*radius);
}

Jika nilai radius mencapai 2.0, kondisi radius != 2.0 akan tetap bernilai false dan loop akan berakhir, tetapi sayangnya hal itu tidak terjadi. Nilai terakhirnya sebelum 2 adalah nilai pendekatan, 1.999999… dan nilai berikutnya adalah 2.199999… jadi ia tidak akan mencapai nilai 2.0.

Gambar 3-8


Latihan
Loop for Berbasis Koleksi
Salah satu terapan dari loop for berbasis koleksi adalah untuk menjejak enumerasi. Di sini, akan ditunjukkan bagaimana loop for berbasis koleksi dipakai untuk menjejak semua nilai pada sebuah enumerasi.

public class LoopForKoleksi {
enum Musim {semi, panas, gugur, dingin} // Definisi tipe enumerasi
   
   public static void main(String[] args) {
      for(Musim musim : Musim.values()) {
         System.out.println("Musim sekarang adalah " + musim);
      }
   }
}

Keluaran program:

Musim sekarang adalah semi
Musim sekarang adalah panas
Musim sekarang adalah gugur
Musim sekarang adalah dingin

Penjelasan
Gambar 3-8 menjelaskan bagaimana loop for berbasis koleksi dipakai. Variabel musim bertipe Musim yang ditempatkan sebagai ekspresi pengendali pertama pada loop for akan ditugasi nilai konstanta enumerasi berbeda pada tiap iterasi loop. Ekspresi kendali kedua, setelah titik-dua, mengidentifikasi koleksi yang merupakan sumber nilai untuk variabel yang dideklarasikan pada ekspresi pengendali pertama. Pada kasus ini, sumber nilai adalah sebuah enumerasi, tetapi umumnya, ada sejumlah koleksi yang dapat Anda gunakan, seperti array dan objek koleksi pada kelas Collection. Pada bab mendatang, Anda akan belajar tentang array dimana kedua jenis loop for dapat dipakai.

Pada contoh ini, enumerasi mendefinisikan empat nilai: semi, panas, gugur, dan dingin, jadi variabel musim akan ditugasi tiap nilai ini secara bergiliran, seperti yang ditunjukkan pada keluaran program.


Latihan
Loop while
Anda dapat menuliskan program untuk menjumlahkan integer-integer kembali menggunakan loop while, yang akan menunjukkan pada Anda bagaimana mekanisme loop ini berbeda dari loop for:

public class LoopWhile {
   
   public static void main(String[] args) {
      int limit = 20;      // Menjumlahkan dari 1 sampai nilai ini
      int sum = 0;         // Mengakumulasikan penjumlahan pada variabel ini
      int i = 1;           // Pencacah loop

      // Loop dari 1 sampai nilai limit,
      // Menambahkan 1 pada tiap siklus
      while(i <= limit) {
         sum += i++; // Menambahkan nilai terkini dari 1 pada sum
      }

      System.out.println("sum = " + sum);
   }
}

Keluaran program sama dengan contoh sebelumnya.

Penjelasan
Loop while dikendalikan secara total oleh ekspresi logikal yang ada di dalam kurung setelah katakunci while. Loop ini berlanjut dieksekusi sepanjang ekspresi ini memiliki nilai true. Anda perlu memastikan bahwa statemen-statemen di dalam loop pada akhirnya akan menyebabkan ekspresi logikal ini bernilai false. Jika tidak, Anda akan memiliki sebuah loop yang akan terus dieksekusi secara tak berhingga.

Bagaimana loop berhenti dieksekusi cukup jelas pada contoh ini. Anda memiliki pencacah sederhana seperti sebelumnya, dan Anda menginkremen i pada statemen loop yang mengakumulasi penjumlahan integer. Cepat atau lambat, i akan melebihi limit, dan loop while akan berhenti dieksekusi.


Latihan
Loop do while
Seperti yang telah disebutkan, loop do while bekerja sama seperti loop while, kecuali fakta bahwa kondisi pengujian diperiksa di akhir loop. Anda dapat menuliskan-ulang program penjumlah integer dengan jenis loop ini:

public class LoopDoWhile {
   
   public static void main(String[] args) {
      int limit = 20;      // Menjumlahkan dari 1 sampai nilai ini
      int sum = 0;         // Mengakumulasikan penjumlahan pada variabel ini
      int i = 1;           // Pencacah loop

      // Loop dari 1 sampai nilai limit,
      // Menambahkan 1 pada tiap siklus
      do {
         sum += i++; // Menambahkan nilai terkini dari 1 pada sum
      } while(i <= limit);

      System.out.println("sum = " + sum);
   }
}

Keluaran program sama dengan contoh sebelumnya.

Penjelasan
Statemen-statemen di dalam loop selalu dieksekusi sedikitnya sekali karena kondisi yang menentukan apakah loop akan berlanjut diuji di akhir dari tiap iterasi. Di dalam loop, Anda menambahkan nilai i pada sum, dan kemudian menginkremennya. Ketika i melebihi nilai dari limit, loop akan berhenti, dimana pada titik itu sum akan memuat penjumlahan atas semua integer dari 1 sampai limit.

Statemen loop di sini memiliki kurung-kurawal yang mengapit blok kode yang berada di dalam loop. Anda dapat menuliskan ulang loop sehingga satu-satunya statemen berada di dalam loop, tanpa adanya kurung-kurawal. Sebagai contoh:

do
   sum += i++; // Menambahkan nilai terkini dari 1 pada sum
while(i <= limit);

Tentu, Anda tetap direkomendasikan untuk selalu menggunakan kurung-kurawal untuk mengapit blok kode yang ada di dalam loop, meski jika blok kode tersebut hanyalah satu buah statemen.


Loop Bersarang
Anda dapat menyarangkan loop di dalam loop lain. Lihat contoh berikut:

Latihan
Menghitung Faktorial
Contoh ini akan menghitung faktorial dari tiap integer dari 1 sampai batas tertentu. Ketikkan kode berikut:

public class Faktorial {
   
   public static void main(String[] args) {
      long limit = 20L;    // Menghitung faktorial integer sampai nilai ini
      long faktorial = 1L; // Hasilnya disimpan pada variabel ini

      // Loop dari 1 sampai limit
      for (long i = 1L; i <= limit; i++) {
         faktorial = 1L; // Menginisialisasi faktorial
        
         for (long faktor = 2; faktor <= i; faktor++) {
            faktorial *= faktor;
         }
         System.out.println(i + "! adalah " + faktorial);
      }
   }
}

Keluaran program:

1! adalah 1
2! adalah 2
3! adalah 6
4! adalah 24
5! adalah 120
6! adalah 720
7! adalah 5040
8! adalah 40320
9! adalah 362880
10! adalah 3628800
11! adalah 39916800
12! adalah 479001600
13! adalah 6227020800
14! adalah 87178291200
15! adalah 1307674368000
16! adalah 20922789888000
17! adalah 355687428096000
18! adalah 6402373705728000
19! adalah 121645100408832000
20! adalah 2432902008176640000

Penjelasan
Semua variabel yang digunakan pada contoh ini bertipe long. Nilai-nilai faktorial membesar sangat cepat sehingga penggunaan tipe long sangat tepat untuk menampung nilai-nilai faktorial yang lebih besari daripada bila Anda menggunakan tipe int. Anda sebenarnya masih bisa mendeklarasikan faktor dan i sebagai tipe int tanpa perlu membatasi ukuran nilai faktorial yang dapat dihasilkan program, tetapi kompilator kemudian perlu menyisipkan konversi tipe untuk membuat nilai int menjadi tipe long.

Loop terluar, yang dikendalikan i, menjejak semua integer dari 1 sampai nilai dari limit. Pada tiap iterasi dari loop terluar, variabel faktorial diinisialisasi dengan 1, dan loop bersarang menghitung faktorial atas nilai terkini dari i menggunakan faktor sebagai pencacah pengendali yang dijalankan dari 2 sampai nilai terkini dari i. Hasil dari faktorial kemudian ditampilkan sebelum menjejak iterasi selanjutnya dari loop terluar.

Meskipun Anda memiliki sebuah loop for bersarang di dalam loop for lain di sini, seperti dijelaskan sebelumnya, Anda dapat menyarangkan sembarang jenis loop di dalam sembarang jenis loop lainnya. Anda dapat menuliskan loop bersarang sebagai berikut:

// Loop dari 1 sampai limit
for (long i = 1L; i <= limit; i++) {
   faktorial = 1L; // Menginisialisasi faktorial
   long faktor = 2L;
        
   while (faktor <= i) {
      faktorial *= faktor++;
   }
   System.out.println(i + "! adalah " + faktorial);
}

Sekarang, Anda memiliki sebuah loop while yang bersarang di dalam sebuah loop for. Keluaran program sama seperti sebelumnya.


Statemen continue
Ada beberapa situasi dimana Anda ingin melompati semua atau sebagian dari iterasi loop. Dimisalkan bahwa Anda ingin menjumlahkan nilai-nilai dari integer 1 sampai batas tertentu, dimana Anda tidak ingin melibatkan integer-integer yang merupakan kelipatan tiga. Anda dapat melakukan ini menggunakan if dan continue:

for (int i = 1; i <= limit; i++)
   if(i % 3 == 0) {
      continue;      // Melompati sisa iterasi
   }
   sum += i;  // Menjumlahkan nilai terkini dari i pada sum
}

Statemen continue dieksekusi pada contoh ini ketika i merupakan kelipatan 3, yang menyebabkan sisa dari iterasi loop terkini dilompati. Eksekusi program dilanjutkan ke iterasi selanjutnya jika ada, jika tidak, dilanjutkan ke statemen pertama yang ada setelah blok loop. Statemen continue dapat ditempatkan di mana saja di dalam blok loop. Anda bahkan bisa memiliki lebih dari satu continue pada sebuah loop.


Statemen continue Berlabel
Ketika Anda memiliki loop bersarang, ada bentuk spesial dari statemen continue yang memampukan Anda untuk menghentikan eksekusi atas loop terdalam (loop bersarang), bukan hanya menghentikan eksekusi atas iterasi terkini dari loop bersarang. Eksekusi program kemudian dilanjutkan ke iterasi selanjutnya dari loop terluar. Ini dinamakan dengan statemen continue berlabel.

Untuk menggunakan statemen continue berlabel, Anda perlu mengidentifikasi statemen loop sebagai loop terluar pengapit menggunakan label statemen. Label statemen adalah sebuah pengenal yang dipakai untuk mengakses statemen tertent. Ketika Anda mengakses statemen tertentu, Anda menuliskan label statemen di awal statemen tersebut, yang dipisahkan dengan titik-dua. Lihat contoh berikut:

Latihan
Statemen continue Berlabel
Anda dapat menambahkan sebuah statemen continue berlabel untuk mengabaikan perhitungan faktorial atas nilai-nilai ganjil yang lebih besar dari 10.

public class ContinueBerlabel {
   
   public static void main(String[] args) {
      long limit = 20L;    // Menghitung faktorial integer sampai nilai ini
      long faktorial = 1L; // Hasilnya disimpan pada variabel ini

      LoopTerluar:
      // Loop dari 1 sampai limit
      for (long i = 1L; i <= limit; i++) {
         faktorial = 1L; // Menginisialisasi faktorial
        
         for (long j = 2; j <= i; j++) {
              if(i > 10L && i % 2L == 1L) {
               continue LoopTerluar; // Pindah ke loop terluar
            }
            faktorial *= j;
         }
         System.out.println(i + "! adalah " + faktorial);
      }
   }
}

Keluaran program:

1! adalah 1
2! adalah 2
3! adalah 6
4! adalah 24
5! adalah 120
6! adalah 720
7! adalah 5040
8! adalah 40320
9! adalah 362880
10! adalah 3628800
12! adalah 479001600
14! adalah 87178291200
16! adalah 20922789888000
18! adalah 6402373705728000
20! adalah 2432902008176640000

Penjelasan
Loop terluar memiliki label LoopTerluar. Pada loop bersarang, ketika kondisi pada statemen if bernilai true, statemen continue berlabel akan dieksekusi yang menyebabkan kendali program berpindah ke awal dari iterasi berikutnya dari loop terluar. Kondisi pada statemen if menyebabkan perhitungan atas faktorial dilompati untuk nilai-nilai ganjil yang lebih besar dari 10.


Menggunakan Statemen break Pada Loop
Anda telah melihat bagaimana menggunakan statemen break pada sebuah blok switch. Efeknya adalah untuk keluar blok switch dan melanjutkan eksekusi ke statemen pertama yang ada setelah blok switch. Anda dapat pula menggunakan statemen break untuk keluar dari sebuah loop. Ketika break dieksekusi di dalam sebuah loop, loop tersebut akan berhenti dieksekusi, dan kendali program akan berlanjut ke statemen pertama yang ada setelah loop. Untuk mendemonstrasikannya, Anda akan menuliskan sebuah program untuk mencari nilai-nilai prima.

Latihan
Menghitung Prima I
Kode berikut sedikit lebih panjang dari contoh sebelumnya. Program ini akan menemukan semua bilangan prima dari 2 sampai 50:

public class Prima {
   public static void main(String[] args) {
      int nNilai = 50; // Nila maksimum yang diperiksa
      boolean apaPrima = true; // Bernilai true jika ditemukan prima

      // Memeriksa semua nilai dari 2 sampai nNilai
      for(int i = 2; i <= nNilai; i++) {
         apaPrima=true; // Asumsi i terkini adalah prima

         // Coba membagi semua integer dari 2 sampai i-1
         for(int j = 2; j < i; j++) {
            if(i % j == 0) { // Bernilai true jika dibagi habis oleh j
               apaPrima = false; // Jika sampai di sini, berarti pembagian habis
               break; // keluar loop
            }
         }
        
         // Anda dapat sampai di sini melalui break,
         // atau setelah menuntaskan loop
         if(apaPrima) // jadi, apa prima?
            System.out.println(i); // ya, tampilkan keluaran
      }
   }
}

Keluaran programm:

2
3
5
7
11
13
17
19
23
29
31
37
41
43
47

Penjelasan
Ada banyak cara efisien untuk menghitung bilangan prima, tetapi program ini cukup untuk mendemonstrasikan statemen break. Langkah pertama pada main() adalah mendeklarasikan dua variabel:

int nNilai = 50; // Nila maksimum yang diperiksa
boolean apaPrima = true; // Bernilai true jika ditemukan prima
Variabel pertama adalah batas atas untuk integer-integer yang akan diperiksa keprimaannya. Variabel apaPrima akan dipakai untuk merekam apakah nilai tertentu prima atau bukan.

Ide dasar dari program adalah menjejak integer dari 2 sampai nilai dari nNilai dan memeriksa setiap integer tersebut untuk melihat apakah integer tersebut habis dibagi oleh integer-integer lain selain dirinya sendiri. Loop-loop berikut melakukannya:

// Memeriksa semua nilai dari 2 sampai nNilai
for(int i = 2; i <= nNilai; i++) {
   apaPrima=true; // Asumsi i terkini adalah prima

   // Coba membagi semua integer dari 2 sampai i-1
   for(int j = 2; j < i; j++) {
      if(i % j == 0) { // Bernilai true jika dibagi habis oleh j
         apaPrima = false; // Jika sampai di sini, berarti pembagian habis
         break; // keluar loop
      }
}

Loop terluar diindeks oleh i dan menjejak semua nilai yang perlu diperiksa keprimaannya. Loop terdalam diindeks oleh j yang merupakan nilai pembagi. Ini menentukan keprimaan atas setiap integer yang nilainya kurang dari nilai yang sedang diuji.

Pemeriksaan dilakukan pada statemen if di dalam loop terdalam. Jika i habis dibagi oleh j tanpa sis, berarti i%j menghasilkan 0, jadi apaPrima akan bernilai false. Pada kasus ini, statemen break akan dieksekusi untuk keluar dari loop terdalam. Tidak ada gunanya lagi bila melanjutkan eksekusi jika nilai yang sedang diuji bukanlah bilangan prima.

Statemen selanjutnya yang akan dieksekusi adalah statemen if yang ada setelah kurung-kurawal penutup dari blok loop terdalam. Eksekusi program dapat mencapai titik ini melalui cara keluar normal dari loop yang terjadi ketika nilai yang diuji adalah bilangan prima. Variabel apaPrima menyelesaikan masalah ini dan jika ia bernilai true, maka Anda memiliki nilai prima yang akan ditampilkan.

Latihan
Menghitung Prima II
Cobalah melakukan perubahan-perubahan ini pada kode pada kelas Prima:

public class Prima2 {
   public static void main(String[] args) {
      int nNilai = 50; // Nila maksimum yang diperiksa

      // Memeriksa semua nilai dari 2 sampai nNilai
      LoopTerluar:
      for(int i = 2; i <= nNilai; i++) {
         // Coba membagi semua integer dari 2 sampai i-1
         for(int j = 2; j < i; j++) {
            if(i % j == 0) { // Bernilai true jika dibagi habis oleh j
               continue LoopTerluar; // keluar loop
            }
         }
        
         // Anda dapat sampai di sini hanya ketika memiliki sebuah bilangan prima
         System.out.println(i); // ya, tampilkan keluaran
      }
   }
}

Jika Anda melakukannya dengan benar, Anda akan mendapatkan keluaran yang sama seperti contoh sebelumnya.

Penjelasan
Anda tidak lagi memerlukan variabel apaPrima untuk mengindikasikan apakah Anda memiliki nilai prima atau tidak, karena statemen keluaran dapat dicapai hanya melalui cara keluar normal dari loop terdalam. Ketika ini terjadi, maka Anda memiliki bilangan prima. Jika Anda mendapatkan bahwa i dapat dibagi habis oleh j pada loop terdalam, maka ini mengimplikasikan bahwa nilai terkini dari i bukanlah bilangan prima, jadi statemen continue berlabel mengalihkan eksekusi ke iterasi selanjutnya pada loop terluar.


Keluar dari Loop Tak-Tentu
Anda bisa jadi memerlukan sebuah loop yang banyak iterasinya tidak bisa Anda ketahui sebelumnya. Ini bisa terjadi ketika Anda memproses item-item data eksternal yang dibaca dari keyboard, misalnya, dan Anda tidak mengetahui berapa banya item data tersebut. Anda dapat menggunakan sebuah loop while, dengan kondisi loop menentukan kapan loop akan berhenti, tetapi ada kalanya hal itu lebih mudah dilakukan menggunakan sebuah loop tak-tentu dan menggunakan statemen break di dalam tubuh loop untuk mengakhiri loop. Loop tak-tentu adalah sebuah loop dimana mekanisme kendalinya diciptakan sehingga loop dapat tetap dieksekusi dengan banyak iterasi tak ditentukan. Pada kasus ini, mekanisme untuk mengakhiri loop harus ditempatkan di dalam tubuh loop.


Latihan
Menghitung Prima III
Dimisalkan bahwa Anda menginginkan agar program Prima membangkitkan sejumlah bilangan prima, bukan memeriksa nilai integer tertentu. Pada kasus ini, Anda tidak mengetahui berapa banyak nilai yang perlu diperiksa untuk menghasilkan sejumlah bilangan prima yang diperlukan. Inilah sebuah kasus dimana sebuah loop tak-tentu berguna. Anda dapat melakukannya sebagai berikut:

public class Prima3 {
   public static void main(String[] args) {
      int nPrima = 50; // Banyak prima yang dihasilkan

      // Memeriksa semua nilai dari 2 sampai nNilai
      LoopTerluar:
      for(int i = 2; ; i++) { // Loop ini berjalan selamanya
         // Coba membagi semua integer dari 2 sampai i-1
         for(int j = 2; j < i; j++) {
            if(i % j == 0) { // Bernilai true jika dibagi habis oleh j
               continue LoopTerluar; // keluar loop
            }
         }
        
         // Anda dapat sampai di sini hanya ketika memiliki sebuah bilangan prima
         System.out.println(i); // ya, tampilkan keluaran
        
         if(--nPrima == 0) { // Mendekremen cacah prima
            break;
         }
      }
   }
}

Program ini akan menampilkan 50 bilangan pertama.

Penjelasan
Program ini sangat mirip dengan versi sebelumnya. Perbedaan utamanya adalah bahwa nPrima memuat banyak prima yang diperlukan, jadi program akan menghasilkan 50 bilangan prima pertama, bukan mencari bilangan prima antara 2 sampai 50, dan loop terluar for, yang dikendalikan i, memiliki kondisi loop yang diabaikan, jadi loop tidak memiliki mekanisme langsung untuk mengakhiri loop. Loop harus dihentikan oleh kode di dalam loop; jika tidak, loop akan dieksekusi selamanya.

Di sini penghentian eksekusi atas loop terluar dikendalikan oleh statemen if yang ada setelah statemen keluaran. Ketika sebuah bilangan prima dihasilkan, nilai tersebut akan ditampilkan, dan nilai dari nPrima didekremen pada statemen if berikut:

if(--nPrima == 0) { // Mendekremen cacah prima
   break;
}

Statemen break akan dieksekusi ketika nPrima didekremen menjadi nol, dan ini akan menghentikan eksekusi loop terluar.


Statemen break Berlabel
Java juga menyediakan statemen break berlabel bagi Anda. Ini memampukan Anda untuk melompat ke statemen yang ada setelah akhir dari blok penutup atau akhir dari loop. Label mengawali kurung-kurawal pembuka dari blok yang diidentifikasinya. Gambar 3-9 mengilustrasikan bagaimana statemen break berlabel bekerja. Statemen break berlabel dapat dipakai untuk keluar dari blok atau loop yang memiliki label, tanpa memandang berapa banyak level blok-blok bersarang.

Gambar 3-9

Lihat bagaimana Anda bisa mengubah contoh sebelumnya dengan menggunakan sebuah statemen break berlabel:

public class Prima4 {
   public static void main(String[] args) {
      int nPrima = 50; // Banyak prima yang dihasilkan

      // Memeriksa semua nilai dari 2 sampai nNilai
      LoopTerluar:
      for(int i = 2; ; i++) { // Loop ini berjalan selamanya
         // Coba membagi semua integer dari 2 sampai i-1
         for(int j = 2; j < i; j++) {
            if(i % j == 0) { // Bernilai true jika dibagi habis oleh j
               continue LoopTerluar; // keluar loop
            }
         }
        
         // Anda dapat sampai di sini hanya ketika memiliki sebuah bilangan prima
         System.out.println(i); // ya, tampilkan keluaran
        
         if(--nPrima == 0) { // Mendekremen cacah prima
            break LoopTerluar;
         }
      }
      // Keluar LoopTerluar
   }
}

Program ini bekerja sama persis seperti contoh sebelumnya. Statemen break berlabel mengakhiri operasi loop yang diawali dengan label LoopTerluar, dan sangat efektif untuk keluar ke titik yang diindikasikan oleh komentar.

















No comments: