1. Biểu thức vs Câu lệnh
Trong Java, mọi phần tử đều chia làm hai loại: câu lệnh (Statement) và biểu thức (Expression). Với câu lệnh, ta nói rằng nó được thực thi, còn với biểu thức — nó được tính toán. Nhưng đó không phải điểm quan trọng nhất.
Khác biệt cốt lõi giữa câu lệnh và biểu thức là biểu thức có kết quả tính toán. Kết quả này, thứ nhất, có một kiểu; thứ hai, có thể được gán ở đâu đó, hoặc dùng tiếp trong một biểu thức khác.
Ví dụ:
| Mã | Ghi chú |
|---|---|
|
Câu lệnh |
|
Biểu thức, kiểu boolean |
|
Biểu thức, kiểu trùng với kiểu của biến i |
|
Biểu thức, kiểu trùng với kiểu của biến x |
Điều đó mang lại gì cho chúng ta?
Thứ nhất, ta có thể tận dụng thực tế rằng rất nhiều câu lệnh thực ra là biểu thức (có kết quả). Ví dụ, đoạn mã sau sẽ hoạt động:
int x, y, z;
x = y = z = 1; // x = (y = (z = 1));
Thứ hai, ta có thể bỏ qua kết quả tính toán của biểu thức nếu muốn.
console.nextLine(); // bỏ qua kết quả nhập
Việc bỏ qua kết quả của một biểu thức cần thiết khi biểu thức, ngoài việc trả về kết quả, còn thực hiện điều gì đó hữu ích mà ta cần hành động đó, còn bản thân kết quả thì không.
2. Toán tử ba ngôi
Mẹo này thú vị hơn cái trước. Trong Java có toán tử ba ngôi (toán tử điều kiện) đặc biệt. Nó phần nào giống dạng rút gọn của if–else:
Uslovie ? Vyrazhenie1 : Vyrazhenie2;
Nếu điều kiện đúng, thì thực hiện biểu thức 1, ngược lại thực hiện biểu thức 2. Sau điều kiện là dấu hỏi, còn hai biểu thức được phân tách bằng dấu hai chấm.
Điểm khác biệt chính giữa toán tử ba ngôi và if-else là toán tử ba ngôi là một biểu thức, do đó kết quả của nó có thể được gán cho một biến.
Ví dụ, ta muốn tính giá trị nhỏ nhất của hai số. Dùng toán tử ba ngôi, mã sẽ như sau:
int a = 2;
int b = 3;
int min = a < b ? a : b;
Hoặc giả sử bạn cần gán cho một biến các giá trị khác nhau tùy theo điều kiện nào đó. Làm thế nào?
Phương án một — dùng if-else:
int age = 25;
int money;
if (age > 30)
money = 100;
else
money = 50;
Phương án hai — dùng toán tử ba ngôi, tức cách viết rút gọn của if-else:
int age = 25;
int money = age > 30 ? 100 : 50;
Vậy nên dùng cái nào: if-else hay toán tử ba ngôi? Về tốc độ thực thi thì hầu như không khác. Chủ yếu là vấn đề dễ đọc. Đây là điểm rất quan trọng: mã không chỉ cần chạy đúng mà còn phải dễ đọc với những lập trình viên khác.
Tiêu chí đơn giản có thể là: nếu mã nằm gọn trong một dòng — hãy dùng toán tử ba ngôi; nếu không còn gọn trong một dòng — nên dùng if-else.
3. Những điểm cần lưu ý
Kiểu của giá trị
Cần nhớ: cả hai nhánh của toán tử ba ngôi (<gia_tri_neu_dung> và <gia_tri_neu_sai>) phải cùng một kiểu, hoặc tương thích (ví dụ cả hai đều String, hoặc cả hai đều int).
Hoạt động:
int a = 10, b = 20;
int max = (a > b) ? a : b; // cả hai nhánh — int
Lỗi biên dịch:
int a = 10, b = 20;
// String và int không tương thích
String result = (a > b) ? "lớn hơn" : 0; // Lỗi biên dịch: không thể gán int cho biến kiểu String
Cách đúng:
int a = 10, b = 20;
String result = (a > b) ? "lớn hơn" : "nhỏ hơn hoặc bằng";
Ví dụ: làm việc với số
Tính giá trị tuyệt đối bằng toán tử ba ngôi:
int number = -5;
int abs = (number >= 0) ? number : -number;
System.out.println(abs); // 5
4. Nhúng toán tử ba ngôi vào ứng dụng
Hãy viết một ứng dụng đối thoại đơn giản: ngoài lời chào, chương trình sẽ nói cho người dùng biết sang năm họ bao nhiêu tuổi và cho biết họ có là người thành niên hay không.
System.out.print("Nhập tên của bạn: ");
String name = console.nextLine();
System.out.print("Nhập tuổi của bạn: ");
int age = console.nextInt();
int nextYear = age + 1;
String status = (nextYear >= 18) ? "thành niên" : "chưa thành niên";
System.out.println("Xin chào, " + name + "! Năm sau bạn sẽ " + nextYear + " tuổi. Bạn sẽ " + status + ".");
Giải thích chi tiết:
Biến status được tính bằng toán tử ba ngôi: nếu tuổi vào năm sau không nhỏ hơn 18 thì người dùng sẽ là (hoặc tiếp tục là) người thành niên.
5. Toán tử ba ngôi lồng nhau — hãy cẩn thận!
Có thể lồng các toán tử ba ngôi vào nhau (mỗi nhánh lại chứa một toán tử ba ngôi khác). Nhưng… điều này thường gây “đau đầu”, đặc biệt cho người đọc mã sau bạn (kể cả chính bạn sau 2 ngày).
Ví dụ: phân loại theo độ tuổi
String category = (age < 7) ? "mẫu giáo" :
(age < 18) ? "học sinh" :
(age < 65) ? "người lớn" : "người nghỉ hưu";
Bảng quyết định:
| Tuổi | Điều kiện | Kết quả |
|---|---|---|
| < 7 | |
mẫu giáo |
| 7–17 | |
học sinh |
| 18–64 | |
người lớn |
| 65 và hơn | ngược lại | người nghỉ hưu |
Đoạn mã như vậy vẫn còn đọc được, nhưng nếu logic phức tạp hơn — tốt hơn hãy dùng if-else if-else.
6. Mẹo: toán tử ba ngôi và kiểu boolean
Đôi khi ta viết một biểu thức kiểu:
boolean adult = (age >= 18) ? true : false;
Nhưng điều này là dư thừa. Bản thân biểu thức (age >= 18) đã trả về boolean. Vì vậy có thể rút gọn thành:
boolean adult = (age >= 18);
GO TO FULL VERSION