Backend

99 Ngày Java — Ngày 04: Toán tử & biểu thức

SSite Admin
31 tháng 07, 2026 5 phút đọc 78 lượt xem
99 Ngày Java — Ngày 04: Toán tử & biểu thức

Hôm qua bạn đã có những chiếc hộp dữ liệu — biến và 8 kiểu nguyên thủy. Hôm nay ta cho chúng "nói chuyện" với nhau bằng toán tử: cộng trừ nhân chia, so sánh, logic, toán tử 3 ngôi — và bẫy độ ưu tiên khiến 2 + 3 * 4 không bằng 20.

Sketchnote Ngày 04: Toán tử và biểu thức trong Java

Toán tử số học

Năm toán tử quen thuộc: + - * / %. Nhưng Java có một bất ngờ lớn cho người mới: hai số nguyên chia nhau ra số nguyên — phần thập phân bị cắt bỏ không thương tiếc:

int a = 7, b = 2;
System.out.println(a + b);   // 9
System.out.println(a - b);   // 5
System.out.println(a * b);   // 14
System.out.println(a / b);   // 3   — chia NGUYÊN: phần thập phân bị cắt!
System.out.println(a % b);   // 1   — số dư (modulo)
System.out.println(7.0 / 2); // 3.5 — có double tham gia là chia thực

Toán tử % (lấy dư) hữu ích hơn vẻ ngoài của nó: n % 2 == 0 kiểm tra số chẵn, index % size quay vòng chỉ số mảng, seconds % 60 tách phút–giây. Còn phép chia nguyên 7 / 2 = 3 là nguồn bug kinh điển khi tính trung bình, tỷ lệ phần trăm — chỉ cần một vế là double (viết 7.0 hoặc cast) là phép chia thành chia thực.

++ và -- : prefix vs postfix

int i = 5;
System.out.println(i++); // in 5, SAU ĐÓ i mới thành 6 (postfix)
System.out.println(++i); // i thành 7 TRƯỚC, rồi mới in 7 (prefix)

int j = 5;
int k = j++ + ++j;       // đọc được, nhưng đừng viết thế này!
  • i++ (postfix) — dùng giá trị cũ trước, tăng sau.

  • ++i (prefix) — tăng trước, rồi mới dùng giá trị mới.

  • Đứng một mình (i++;) thì hai dạng như nhau — và đó là cách dùng nên theo: đừng nhét ++ vào giữa biểu thức phức tạp.

Toán tử gán kết hợp

x += 5 là cách viết gọn của x = x + 5 — tương tự có -=, *=, /=, %=. Một chi tiết ít người biết: toán tử gán kết hợp tự ép kiểu ngầmbyte b = 10; b += 1; chạy ngon, trong khi b = b + 1; lỗi compile vì b + 1int. Chuyện ép kiểu này chính là chủ đề của Ngày 05.

So sánh & logic — và short-circuit

Toán tử so sánh (==, !=, >, <, >=, <=) trả về boolean, rồi được ghép bằng logic && (VÀ), || (HOẶC), ! (PHỦ ĐỊNH):

int age = 20;
boolean hasTicket = true;
boolean canEnter = age >= 18 && hasTicket;   // true

// Short-circuit: vế phải KHÔNG chạy nếu vế trái đã đủ kết luận
String name = null;
if (name != null && name.length() > 0) {
    // an toàn: name.length() chỉ chạy khi name != null
}

Short-circuit là tính năng chứ không phải chi tiết vặt: && thấy vế trái false là dừng ngay, || thấy vế trái true là dừng ngay. Nhờ vậy mẫu name != null && name.length() > 0 trở thành thành ngữ chống NullPointerException mà bạn sẽ gặp ở mọi codebase Java. Lưu ý: với String, so sánh nội dung phải dùng .equals() chứ không phải == — Ngày 09 sẽ mổ xẻ kỹ.

Màn hình code đầy biểu thức — nơi toán tử làm việc ngày đêm

Toán tử 3 ngôi

Toán tử duy nhất nhận 3 toán hạng: điều_kiện ? giá_trị_nếu_đúng : giá_trị_nếu_sai — một biểu thức if-else thu gọn:

int score = 75;
String result = score >= 50 ? "Đậu" : "Rớt";   // "Đậu"

// Tương đương if-else 4 dòng — nhưng chỉ nên dùng khi NGẮN GỌN
int max = a > b ? a : b;

Quy tắc vàng: 3 ngôi dùng cho lựa chọn ngắn, một tầng. Lồng 3 ngôi trong 3 ngôi là cách nhanh nhất khiến đồng nghiệp muốn "nói chuyện riêng" với bạn — khi logic phức tạp, quay về if-else (học kỹ ở Ngày 06).

Độ ưu tiên — khi nghi ngờ, thêm ngoặc

int x = 2 + 3 * 4;        // 14 — nhân trước, cộng sau
int y = (2 + 3) * 4;      // 20 — ngoặc thắng tất cả

boolean t = true || false && false;   // true — && trước ||
boolean u = (true || false) && false; // false — ngoặc đổi kết quả
  • Thứ tự đại khái cần nhớ: !* / %+ - → so sánh → &&|| → gán = cuối cùng.

  • Không ai được thưởng vì thuộc lòng bảng ưu tiên 15 tầng — cứ thêm ngoặc cho người đọc (và chính bạn 6 tháng sau).

Bài tập nhỏ

  • Không chạy code, đoán kết quả: 9 / 4, 9 % 4, 9.0 / 4 — rồi chạy kiểm tra.

  • Cho int i = 10;System.out.println(i++ + ++i) in gì? Giải thích từng bước.

  • Viết biểu thức kiểm tra một năm nhuận: chia hết cho 4 nhưng không chia hết cho 100, hoặc chia hết cho 400.

  • Dùng toán tử 3 ngôi viết hàm trả về trị tuyệt đối của một số int.

Kết luận

Bạn đã nắm đủ bộ toán tử: số học và cú lừa chia nguyên, ++/-- hai dạng, so sánh, logic short-circuit, 3 ngôi và quy tắc "thêm ngoặc khi nghi ngờ". Ngày 05, ta giải quyết câu hỏi treo từ hôm nay: chuyện gì xảy ra khi các kiểu khác nhau gặp nhau trong một biểu thức — ép kiểu (casting), widening vs narrowing và bẫy mất mát dữ liệu. Hẹn gặp lại!

S

Site Admin

Engineer and writer. Building things with TypeScript and distributed systems.

Bình luận (0)

Bạn cần đăng nhập bằng Google để bình luận.

Hãy là người bình luận đầu tiên.

Bài viết liên quan

99 Ngày Spring — Ngày 14: Bean Validation — @Valid & bộ constraint chuẩn

Ngày 14 của 99 Ngày Spring: Bean Validation khai báo luật ngay trên DTO — @Valid kích hoạt, bộ constraint chuẩn (@NotBlank vs @NotEmpty vs @NotNull, @Size, @Email, @Min/@Max), bẫy int vs Integer, validate object lồng nhau không tự lan, và lỗi 400 gom một lượt.

10 thg 8, 20265 phút0
99 Ngày Java — Ngày 14: Kế thừa (Inheritance)

Ngày 14 của 99 Ngày Java: extends trao gia tài từ lớp cha, override với @Override và super., thứ tự khai sinh cha trước con sau qua super(...), protected trả nợ Ngày 13, và phép thử is-a vs has-a — khi nào nên composition thay vì kế thừa.

10 thg 8, 20266 phút0
99 Ngày Spring — Ngày 13: @RequestBody & DTO — đừng công khai entity ra API

Ngày 13 của 99 Ngày Spring: @RequestBody + Jackson deserialize JSON thành object, DTO là hợp đồng API — chặn lỗ hổng mass assignment chiều vào và rò rỉ dữ liệu chiều ra, request/response DTO khác nhau là bình thường, và Jackson annotations tinh chỉnh hợp đồng JSON.

9 thg 8, 20266 phút9