Tampilan
Kenapa penting
Kode backend jarang berjalan lurus dari atas ke bawah. Kamu memutuskan apakah request valid, memilih tarif sesuai zona pengiriman, mengulang panggilan ke API pembayaran yang sedang sibuk, atau memproses data halaman demi halaman. Semua itu adalah kontrol alur: cara program memilih jalur (percabangan) dan mengulang pekerjaan (perulangan). Menguasai bentuk-bentuknya — terutama switch expression modern — membuat logika bisnismu ringkas dan minim bug.
Konsep inti
if, else if, else
if menjalankan sebuah blok hanya jika kondisinya true. Kondisi selalu bertipe boolean — hasil operator perbandingan dan logika yang kamu pelajari di bab sebelumnya.
java
public class StockLevel {
public static void main(String[] args) {
int stock = 3;
if (stock == 0) {
System.out.println("Habis");
} else if (stock < 5) {
System.out.println("Hampir habis: sisa " + stock);
} else {
System.out.println("Tersedia");
}
}
}Output: Hampir habis: sisa 3. Kondisi diperiksa dari atas; begitu satu cabang cocok, cabang lain dilewati. Biasakan selalu memakai kurung kurawal { } walaupun isinya satu baris — lebih aman saat kode bertambah.
Switch expression
Saat satu nilai dibandingkan dengan banyak kemungkinan, rantai else if cepat jadi panjang. Switch expression (final sejak Java 14) lebih ringkas: setiap case memakai panah ->, boleh berisi beberapa label sekaligus, dan seluruh switch menghasilkan nilai yang bisa langsung disimpan ke variabel.
java
public class DayType {
public static void main(String[] args) {
String day = "SABTU";
String type = switch (day) {
case "SENIN", "SELASA", "RABU", "KAMIS", "JUMAT" -> "hari kerja";
case "SABTU", "MINGGU" -> "akhir pekan";
default -> "tidak dikenal";
};
System.out.println(day + " = " + type);
}
}Output: SABTU = akhir pekan. Perhatikan titik koma setelah } — karena switch di sini adalah ekspresi di dalam pernyataan deklarasi variabel.
Switch expression harus exhaustive: setiap kemungkinan nilai wajib menghasilkan sesuatu. Untuk int atau String, artinya kamu perlu default; tanpa itu compiler menolak dengan pesan the switch expression does not cover all possible input values.
Jika sebuah cabang butuh lebih dari satu pernyataan, tulis blok { } dan pakai yield untuk menghasilkan nilainya:
java
public class ShippingDays {
public static void main(String[] args) {
String zone = "LUAR_JAWA";
boolean express = true;
int days = switch (zone) {
case "JABODETABEK" -> 1;
case "JAWA" -> 2;
case "LUAR_JAWA" -> {
int base = 5;
yield express ? base - 2 : base;
}
default -> 7;
};
System.out.println("Estimasi tiba: " + days + " hari");
}
}Output: Estimasi tiba: 3 hari.
Switch statement lama dan fall-through
Kamu akan sering menemukan bentuk lama di kode warisan: case dengan titik dua :. Bentuk ini punya perilaku fall-through — setelah satu case cocok, eksekusi terus turun ke case berikutnya sampai bertemu break.
java
public class FallThrough {
public static void main(String[] args) {
int level = 1;
switch (level) {
case 1:
System.out.println("Akses baca");
case 2:
System.out.println("Akses tulis");
break;
default:
System.out.println("Tanpa akses");
}
}
}Output-nya dua baris, Akses baca lalu Akses tulis — pengguna level 1 tiba-tiba mendapat akses tulis karena satu break terlupa. Bentuk panah -> tidak pernah fall-through, jadi untuk kode baru selalu pilih bentuk panah. Bentuk panah juga bisa dipakai sebagai pernyataan biasa (tanpa menghasilkan nilai), misalnya case 1 -> System.out.println("A");.
Perulangan: for, while, do-while
| Loop | Kapan dipakai |
|---|---|
for | jumlah perulangan diketahui atau mengikuti penghitung (1 sampai N) |
while | ulangi selama kondisi benar; jumlahnya belum tentu diketahui di awal |
do-while | seperti while, tetapi badan loop dijalankan minimal sekali |
java
public class Loops {
public static void main(String[] args) {
// for: jumlah perulangan sudah diketahui
for (int page = 1; page <= 3; page++) {
System.out.println("Memuat halaman " + page);
}
// while: ulangi selama kondisi masih benar
int balance = 100_000;
int months = 0;
while (balance < 150_000) {
balance = balance + balance / 10; // bunga 10% per bulan
months++;
}
System.out.println("Saldo " + balance + " setelah " + months + " bulan");
// do-while: badan loop jalan minimal sekali
int attempt = 0;
do {
attempt++;
System.out.println("Percobaan ke-" + attempt);
} while (attempt < 2);
}
}Bagian for terdiri dari tiga: inisialisasi (int page = 1), kondisi (page <= 3), dan pembaruan (page++). Output loop while di atas adalah Saldo 161051 setelah 5 bulan.
break dan continue
breakmenghentikan loop seketika.continuemelewati sisa badan loop dan langsung lanjut ke putaran berikutnya.
java
public class BreakContinue {
public static void main(String[] args) {
for (int orderId = 1; orderId <= 10; orderId++) {
if (orderId % 2 == 0) {
continue; // lewati pesanan genap
}
if (orderId > 7) {
break; // berhenti total
}
System.out.print(orderId + " ");
}
System.out.println();
}
}Output: 1 3 5 7. Pada loop bersarang, break biasa hanya keluar dari loop terdalam. Untuk keluar dari loop luar sekaligus, beri label pada loop itu — jarang dibutuhkan, tapi baik untuk dikenali:
java
public class LabeledBreak {
public static void main(String[] args) {
search:
for (int row = 1; row <= 3; row++) {
for (int col = 1; col <= 3; col++) {
if (row * col == 4) {
System.out.println("Ketemu di baris " + row + ", kolom " + col);
break search;
}
}
}
}
}Scope variabel blok
Variabel yang dideklarasikan di dalam blok { } — termasuk blok if, badan loop, dan variabel penghitung for — hanya hidup sampai akhir blok itu.
java
int stock = 10;
if (stock > 5) {
String message = "Stok aman";
System.out.println(message);
}
System.out.println(message); // error: cannot find symbolKalau nilainya dibutuhkan setelah blok, deklarasikan variabel sebelum blok. Scope yang sempit itu bagus: variabel hanya terlihat di tempat ia dipakai, sehingga lebih sulit disalahgunakan.
Contoh di dunia backend
Layanan pembayaran memanggil API bank yang kadang sibuk (503). Strategi umum: ulangi beberapa kali dengan jeda yang makin panjang (exponential backoff), berhenti jika berhasil, dan jangan mengulang kesalahan klien (4xx) karena hasilnya tidak akan berubah.
java
public class RetryLoop {
public static void main(String[] args) {
int maxAttempts = 4;
int delayMillis = 200;
boolean success = false;
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
int status = attempt < 3 ? 503 : 200; // simulasi: dua panggilan pertama gagal
String result = switch (status / 100) {
case 2 -> "berhasil";
case 4 -> "ditolak";
case 5 -> "server error";
default -> "tidak dikenal";
};
System.out.println("Percobaan " + attempt + ": " + status + " (" + result + ")");
if (status / 100 == 2) {
success = true;
break;
}
if (status / 100 == 4) {
break; // kesalahan klien: mengulang tidak akan membantu
}
System.out.println(" tunggu " + delayMillis + " ms");
delayMillis = delayMillis * 2;
}
System.out.println(success ? "Pembayaran terkonfirmasi" : "Pembayaran gagal");
}
}Output:
text
Percobaan 1: 503 (server error)
tunggu 200 ms
Percobaan 2: 503 (server error)
tunggu 400 ms
Percobaan 3: 200 (berhasil)
Pembayaran terkonfirmasiDi aplikasi nyata, jeda itu benar-benar ditunggu dan jumlah percobaan dibatasi lewat konfigurasi — polanya tetap sama: loop dengan batas, switch untuk memilah hasil, dan break untuk keluar lebih awal. Contoh ini mengulang semua 5xx; di sistem nyata hanya gangguan sementara (mis. 503, 429) yang layak diulang. Di latihan bab ini kamu membangun ketiganya sebagai method: pengelompokan kode status, total jeda retry, dan penentuan kode yang layak di-retry.
Pertanyaan interview
1. Apa beda switch expression dan switch statement lama?
Switch expression memakai ->, menghasilkan nilai, tidak pernah fall-through, dan wajib exhaustive. Switch statement lama memakai : dan akan fall-through ke case berikutnya bila break terlupa — sumber bug klasik.
2. Bagaimana kamu menulis logika retry yang aman saat memanggil layanan lain?
Batasi jumlah percobaan, beri jeda yang makin panjang (exponential backoff, sering ditambah sedikit jeda acak), dan hanya ulangi gangguan sementara seperti 429, 503, atau timeout — bukan kesalahan klien 4xx. Pastikan juga operasinya aman diulang (idempoten), misalnya pembayaran tidak tertagih dua kali.
3. Kapan memakai while dan kapan for?
for cocok bila perulangan mengikuti penghitung atau jumlahnya jelas. while cocok bila kamu mengulang selama kondisi tertentu masih benar, misalnya mengambil data halaman demi halaman sampai habis. do-while dipakai bila badan loop harus jalan minimal sekali.
Jebakan umum
breakterlupa di switch lama → fall-through diam-diam menjalankan cabang berikutnya. Pakai bentuk panah->.- Loop tak berujung — lupa memperbarui variabel kondisi di
while, misalnya tidak menaikkan penghitung. Pastikan setiap putaran membawa kondisi lebih dekat kefalse, dan beri batas maksimum pada loop retry. - Off-by-one —
i <= nversusi < nmenentukan apakah putaran terakhir ikut dijalankan. Cek nilai awal dan nilai akhir secara eksplisit. - Membandingkan
Stringdengan==diif— gunakanequals(if (zone.equals("JAWA"))). Switch padaStringsudah memakaiequalsdi balik layar, jadi aman. - Titik koma setelah
if (...)—if (stock < 5);membuat blok setelahnya selalu jalan karenaif-nya hanya mengatur pernyataan kosong.
Ringkasan
if/else if/elsememilih satu cabang berdasarkan kondisiboolean, diperiksa dari atas ke bawah.- Switch expression (
case ... ->) menghasilkan nilai, mendukung beberapa label percase,yielduntuk blok, dan wajib exhaustive (biasanya dengandefault). - Switch statement lama dengan
:bisa fall-through tanpabreak— hindari untuk kode baru. foruntuk penghitung,whileuntuk kondisi,do-whilebila badan loop harus jalan minimal sekali.breakmenghentikan loop,continuemelompat ke putaran berikutnya; variabel blok hanya hidup di dalam bloknya.