Tampilan
Kenapa penting
Hampir setiap baris logika bisnis adalah ekspresi: menghitung total belanja, menentukan diskon, memeriksa apakah pengguna boleh mengakses sebuah endpoint, atau menghitung offset untuk pagination. Kesalahan kecil di operator — pembagian bulat yang memotong desimal, urutan prioritas yang keliru, atau == pada String — menghasilkan bug yang lolos kompilasi tapi salah di production. Bab ini membuatmu bisa membaca dan menulis ekspresi Java dengan yakin.
Konsep inti
Ekspresi adalah potongan kode yang menghasilkan nilai, misalnya price * quantity atau age >= 17. Ekspresi disusun dari nilai, variabel, dan operator.
Operator aritmatika
| Operator | Arti | Contoh | Hasil |
|---|---|---|---|
+ | tambah | 7 + 2 | 9 |
- | kurang | 7 - 2 | 5 |
* | kali | 7 * 2 | 14 |
/ | bagi | 7 / 2 | 3 |
% | sisa bagi | 7 % 2 | 1 |
Hal terpenting: jika kedua operand bilangan bulat, / menghasilkan bilangan bulat — bagian desimal dibuang. Agar hasilnya pecahan, salah satu operand harus double.
java
public class Arithmetic {
public static void main(String[] args) {
int totalItems = 17;
int pageSize = 5;
System.out.println(totalItems / pageSize); // 3, bukan 3.4
System.out.println(totalItems % pageSize); // 2, sisa bagi
System.out.println(totalItems / 5.0); // 3.4, salah satu operand double
System.out.println((double) totalItems / pageSize);
System.out.println(-7 / 2);
System.out.println(-7 % 2);
System.out.println(5.0 / 0);
}
}Output: 3, 2, 3.4, 3.4, -3, -1, Infinity. Pembagian bulat selalu dipotong ke arah nol, dan hasil % mengikuti tanda operand kiri. Membagi double dengan nol menghasilkan Infinity, sedangkan membagi bilangan bulat dengan nol menghentikan program dengan ArithmeticException.
Operator % sangat berguna untuk mengecek kelipatan: n % 2 == 0 berarti n genap.
Increment, decrement, dan compound assignment
++ menambah 1 dan -- mengurangi 1. Posisinya menentukan nilai yang dikembalikan ekspresi:
- postfix
a++— kembalikan nilai lama, lalu naikkan; - prefix
++a— naikkan dulu, lalu kembalikan nilai baru.
Compound assignment (+=, -=, *=, /=, %=) adalah singkatan x = x op y — dengan satu perbedaan penting: ada cast implisit ke tipe variabel kiri.
java
public class IncrementDemo {
public static void main(String[] args) {
int a = 5;
int b = a++; // b = 5, lalu a menjadi 6
int c = ++a; // a menjadi 7, lalu c = 7
System.out.println(a + " " + b + " " + c);
int score = 10;
score += 5; // score = score + 5
score *= 2; // score = score * 2
score -= 3;
System.out.println(score);
byte level = 10;
level += 5; // boleh: ada cast implisit ke byte
// level = level + 5; // error: hasil level + 5 bertipe int
System.out.println(level);
int total = 10;
total += 2.7; // cast implisit: (int) (10 + 2.7)
System.out.println(total);
}
}Output: 7 5 7, 27, 15, 12. Baris total += 2.7 lolos kompilasi tapi diam-diam membuang 0.7 — seperti cast (int) yang kamu pelajari di bab sebelumnya. Sebaiknya pakai ++/-- sebagai pernyataan tersendiri (count++;), jangan diselipkan di tengah ekspresi yang panjang.
Operator perbandingan
==, !=, <, <=, >, >= membandingkan dua nilai dan menghasilkan boolean. Ingat: = adalah assignment, == adalah perbandingan.
Operator logika dan short-circuit
&&(DAN) —truebila kedua sisitrue;||(ATAU) —truebila minimal satu sisitrue;!(BUKAN) — membalik nilai:!trueadalahfalse.
java
public class LogicDemo {
public static void main(String[] args) {
int age = 20;
boolean hasKtp = true;
boolean banned = false;
boolean canRegister = age >= 17 && hasKtp && !banned;
System.out.println(canRegister);
boolean isWeekend = false;
boolean isHoliday = true;
System.out.println(isWeekend || isHoliday);
System.out.println(age == 20);
System.out.println(age != 20);
}
}Output: true, true, true, false.
&& dan || bersifat short-circuit: sisi kanan hanya dievaluasi bila perlu. Pada false && ... hasilnya pasti false, dan pada true || ... hasilnya pasti true, jadi sisi kanan dilewati. Ini dipakai untuk menjaga agar pemanggilan method tidak terjadi pada null:
java
public class ShortCircuit {
public static void main(String[] args) {
String name = null;
boolean valid = name != null && name.length() > 0;
System.out.println(valid);
int count = 0;
boolean result = false && (++count > 0);
System.out.println(result + " " + count);
boolean result2 = false & (++count > 0);
System.out.println(result2 + " " + count);
}
}Output: false, false 0, false 1. Operator & (satu karakter) pada boolean tidak short-circuit — kedua sisi selalu dievaluasi. Untuk kondisi, hampir selalu pakai && dan ||.
Operator ternary
kondisi ? nilaiJikaTrue : nilaiJikaFalse memilih satu dari dua nilai. Cocok untuk pilihan sederhana; untuk logika bercabang yang lebih rumit, tunggu if dan switch di bab Kontrol Alur.
java
public class TernaryDemo {
public static void main(String[] args) {
int stock = 0;
String label = stock > 0 ? "Tersedia" : "Habis";
System.out.println(label);
int quantity = 12;
int discountPercent = quantity >= 10 ? 15 : 0;
System.out.println(discountPercent);
}
}Output: Habis, lalu 15.
Prioritas operator
Seperti matematika, *, /, % dikerjakan sebelum + dan -. Urutan ringkas dari yang paling kuat:
++/--postfix, lalu prefix,!, cast(tipe)*/%+-(termasuk penggabungan String)<<=>>===!=&&||? :=+=-=dan kawan-kawan
Operator dengan prioritas sama dievaluasi dari kiri ke kanan (kecuali assignment, dari kanan ke kiri).
java
public class Precedence {
public static void main(String[] args) {
System.out.println(2 + 3 * 4);
System.out.println((2 + 3) * 4);
System.out.println(10 - 4 - 3);
System.out.println("Total: " + 2 + 3);
System.out.println("Total: " + (2 + 3));
System.out.println(2 + 3 + " item");
boolean b = true || false && false;
System.out.println(b);
}
}Output: 14, 20, 3, Total: 23, Total: 5, 5 item, true. Begitu salah satu operand + berupa String, + berubah menjadi penggabungan teks. Karena evaluasi dari kiri, "Total: " + 2 + 3 menghasilkan "Total: 23". Aturan praktis: kalau ragu, pakai tanda kurung — kode jadi lebih mudah dibaca rekan setim.
== vs equals pada String
Untuk tipe primitif, == membandingkan nilai. Untuk tipe referensi seperti String, == membandingkan apakah dua variabel menunjuk object yang sama. Untuk membandingkan isi teks, pakai method equals.
java
public class StringEquality {
public static void main(String[] args) {
String role = "admin";
String input = new String("admin");
System.out.println(role == input);
System.out.println(role.equals(input));
}
}Output: false, lalu true. Teks yang datang dari request HTTP atau database hampir selalu object baru, jadi == akan memberi hasil yang membingungkan. Detail perbandingan object dibahas lagi di modul OOP dan Collections.
Contoh di dunia backend
Endpoint daftar produk biasanya mendukung pagination: klien meminta halaman tertentu, server menghitung jumlah halaman dan offset untuk query database.
java
public class Pagination {
public static void main(String[] args) {
long totalRows = 103;
int pageSize = 20;
int page = 3; // halaman dimulai dari 1
long totalPages = (totalRows + pageSize - 1) / pageSize;
long offset = (long) (page - 1) * pageSize;
boolean hasNext = page < totalPages;
boolean validPage = page >= 1 && page <= totalPages;
System.out.println("totalPages=" + totalPages + " offset=" + offset
+ " hasNext=" + hasNext + " validPage=" + validPage);
System.out.println(hasNext ? "Tampilkan tombol Berikutnya" : "Halaman terakhir");
}
}Output:
text
totalPages=6 offset=40 hasNext=true validPage=true
Tampilkan tombol BerikutnyaEkspresi (totalRows + pageSize - 1) / pageSize adalah trik pembulatan ke atas dengan pembagian bulat: 103 baris dengan 20 per halaman butuh 6 halaman, bukan 5. Cast (long) pada offset mencegah overflow untuk halaman yang sangat jauh, dan validPage menggabungkan dua perbandingan dengan &&.
Pertanyaan interview
1. Jelaskan short-circuit evaluation dan contoh pemakaiannya.
&& dan || berhenti mengevaluasi begitu hasilnya sudah pasti: false && ... pasti false, true || ... pasti true. Pola umumnya adalah pemeriksaan null sebelum memanggil method: name != null && name.length() > 0. Operator & dan | pada boolean selalu mengevaluasi kedua sisi.
2. Apa beda == dan equals?
Untuk primitif, == membandingkan nilai. Untuk tipe referensi, == membandingkan apakah dua variabel menunjuk object yang sama, sedangkan equals membandingkan isinya. Untuk String dan wrapper seperti Integer, hampir selalu yang kamu butuhkan adalah equals.
3. Berapa hasil 5 / 2 dan -5 % 2 di Java, dan kenapa?
5 / 2 bernilai 2 karena pembagian dua bilangan bulat membuang desimal (dipotong ke arah nol). -5 % 2 bernilai -1 karena tanda hasil % mengikuti operand kiri. Ini penting saat menghitung pagination atau pembagian jatah.
Jebakan umum
- Pembagian bulat tak sengaja.
int percent = done / total * 100;hampir selalu0. Ubah urutan (done * 100 / total) atau pakaidouble. +pada String."Total: " + a + bmenggabungkan teks, bukan menjumlahkan. Bungkus dengan kurung.==untuk String. Selalu pakaiequalsuntuk membandingkan isi teks.- Urutan short-circuit terbalik.
name.length() > 0 && name != nulltetap melemparNullPointerException; ceknulllebih dulu. ++di tengah ekspresi.int j = i++ + ++i;sulit dibaca dan rawan salah tafsir. Pisahkan menjadi pernyataan sendiri.- Compound assignment membuang data.
total += 2.7padaintmemotong desimal tanpa peringatan.
Ringkasan
/pada dua bilangan bulat membuang desimal;%memberi sisa bagi dan berguna untuk cek kelipatan.a++mengembalikan nilai lama,++anilai baru; compound assignment punya cast implisit.- Perbandingan dan operator logika menghasilkan
boolean;&&/||bersifat short-circuit. - Ternary
kondisi ? a : buntuk memilih nilai sederhana. */%lebih kuat dari+-;&&lebih kuat dari||. Kalau ragu, pakai kurung.- Bandingkan isi String dengan
equals, bukan==.