1. Có gì mới trong switch
Nếu bạn đã viết Java trước phiên bản 14, thì switch trông đại khái như sau:
switch (day)
{
case MONDAY:
System.out.println("Đầu tuần!");
break;
case FRIDAY:
System.out.println("Thứ Sáu, tuyệt!");
break;
default:
System.out.println("Một ngày bình thường.");
break;
}
Có vẻ không có gì ghê gớm, nhưng:
- Cần nhớ break (nếu không sẽ “rơi” sang case tiếp theo).
- Nhiều mã lặp lại.
- Nếu muốn trả về giá trị, phải khai báo biến trước và gán giá trị cho nó bên trong mỗi case.
Java 14+ đã quyết định: đủ rồi! Đã đến lúc làm cho switch tiện dụng và hiện đại hơn.
Những điểm mới chính:
- Switch đã trở thành một biểu thức, không chỉ là câu lệnh — giờ nó có thể trả về giá trị.
- Cú pháp mới với mũi tên -> thay cho dấu hai chấm và break.
- Nhiều case bằng dấu phẩy — cho cùng một logic.
- Trình biên dịch kiểm tra rằng mọi trường hợp đã được xử lý (đặc biệt với enum).
- Không còn rủi ro “rơi qua” (fall-through) — giờ chỉ có thể thực hiện khi bạn chỉ định rõ ràng.
2. Cú pháp của biểu thức switch
switch (znachenie)
{
case A, B -> rezultat1;
case C -> {
// vài thao tác
yield rezultat2;
}
default -> rezultatPoUmolchaniyu;
}
-> và
yield
Ví dụ cơ bản
Vào thẳng vấn đề. Đây là cách giờ bạn có thể trả về giá trị từ switch:
DayOfWeek day = DayOfWeek.MONDAY;
String message = switch (day)
{
case MONDAY, FRIDAY, SUNDAY -> "Tuần ngắn hoặc ngày nghỉ!";
case TUESDAY -> "Thứ Ba là ngày vất vả.";
case WEDNESDAY, THURSDAY -> "Giữa tuần!";
case SATURDAY -> "Tuyệt quá, Thứ Bảy!";
// Bắt buộc phải có default nếu chưa xử lý hết mọi trường hợp
default -> "Một ngày khá kỳ lạ...";
};
System.out.println(message);
Điều gì đang xảy ra ở đây:
- switch (day) — là một biểu thức trả về giá trị.
- Sau mũi tên -> là kết quả cho case đó.
- Có thể gộp nhiều case bằng dấu phẩy.
- Không có bất kỳ break nào — Java tự biết nơi kết thúc nhánh.
- Có thể gán trực tiếp kết quả cho biến message.
Ví dụ với số
int code = 404;
String result = switch (code)
{
case 200 -> "OK";
case 400, 404 -> "Lỗi phía khách hàng";
case 500 -> "Lỗi máy chủ";
default -> "Mã không xác định";
};
System.out.println(result);
Ví dụ với chuỗi
String command = "start";
String status = switch (command)
{
case "start" -> "Khởi động!";
case "stop" -> "Dừng!";
case "pause" -> "Tạm dừng...";
default -> "Lệnh không xác định";
};
System.out.println(status);
Sử dụng khối với yield
Đôi khi bạn muốn thực hiện vài thao tác cho một case (ví dụ, tính toán phức tạp hoặc ghi log). Khi đó có thể dùng khối { ... } và từ khóa yield:
int n = 7;
String parity = switch (n % 2)
{
case 0 -> "Chẵn";
case 1 ->
{
System.out.println("Phát hiện số lẻ: " + n);
yield "Lẻ";
}
default -> "Điều gì đó kỳ lạ";
};
System.out.println(parity);
Quan trọng: trong khối nhất định phải có yield, trả về giá trị cho case đó.
3. Ưu điểm của cú pháp mới
Không cần break
Trong switch cổ điển, quên break là nguồn gốc của đau đầu và bug khó hiểu. Với cú pháp mới, break không cần thiết: mỗi nhánh tự động kết thúc.
Trình biên dịch kiểm tra việc xử lý mọi trường hợp
Nếu bạn dùng enum và không xử lý hết mọi giá trị — trình biên dịch sẽ không cho build dự án nếu thiếu default. Điều này làm mã tin cậy hơn.
Không có “rơi qua” (fall-through)
Trong switch cổ điển, nếu quên break, luồng sẽ “rơi” sang case tiếp theo. Với cú pháp mới điều này không thể xảy ra (trừ khi bạn dùng khối lệnh và cố ý viết break — nhưng ở đây không cần).
Mã ngắn gọn và dễ đọc hơn
Hãy tự so sánh:
Trước:
String result;
switch (status) {
case "OK":
result = "Mọi thứ đều ổn";
break;
case "ERROR":
result = "Lỗi";
break;
default:
result = "Không rõ";
break;
}
Sau:
String result = switch (status) {
case "OK" -> "Mọi thứ đều ổn";
case "ERROR" -> "Lỗi";
default -> "Không rõ";
};
Nhiều case — một logic
case MONDAY, FRIDAY, SUNDAY -> "Ngày nghỉ hoặc ngày ngắn!";
4. So sánh với switch cổ điển
| Đặc điểm | Switch cổ điển | Switch mới |
|---|---|---|
| break là bắt buộc | Có | Không |
| Rơi qua (fall-through) | Có | Không |
| Có thể trả về giá trị | Không (chỉ qua biến) | Có (biểu thức) |
| Nhiều case bằng dấu phẩy | Không | Có |
| Kiểm tra mọi trường hợp | Không | Có (đặc biệt với enum) |
| Độ gọn | Nhiều mã | Ngắn gọn, rõ ràng |
| Dùng với enum và chuỗi | Có | Có |
5. Tương thích với enum và chuỗi
Ví dụ với enum
Giả sử chúng ta có một liệt kê:
enum DayOfWeek
{
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
Dùng nó trong switch mới:
DayOfWeek today = DayOfWeek.WEDNESDAY;
String mood = switch (today)
{
case MONDAY -> "Thật khó để dậy...";
case FRIDAY -> "Cuối tuần sắp đến!";
case SATURDAY, SUNDAY -> "Tuyệt, nghỉ ngơi!";
default -> "Ngày làm việc.";
};
System.out.println(mood);
Ví dụ với String
String season = "summer";
String activity = switch (season)
{
case "winter" -> "Trượt băng";
case "summer" -> "Bơi ở hồ";
case "autumn" -> "Hái nấm";
case "spring" -> "Nghe chim hót";
default -> "Mùa không xác định";
};
System.out.println(activity);
6. Viết lại switch cũ theo phong cách mới
Trước đây:
int day = 3;
String dayName;
switch (day)
{
case 1:
dayName = "Thứ Hai";
break;
case 2:
dayName = "Thứ Ba";
break;
case 3:
dayName = "Thứ Tư";
break;
default:
dayName = "Ngày không xác định";
break;
}
System.out.println(dayName);
Sau khi đổi:
int day = 3;
String dayName = switch (day)
{
case 1 -> "Thứ Hai";
case 2 -> "Thứ Ba";
case 3 -> "Thứ Tư";
default -> "Ngày không xác định";
};
System.out.println(dayName);
Thêm ví dụ: nhiều case — một logic
int score = 5;
String grade = switch (score)
{
case 5, 6, 7 -> "Khá";
case 8, 9, 10 -> "Xuất sắc";
default -> "Cần cố gắng";
};
System.out.println(grade);
7. Lỗi thường gặp và lưu ý
Lỗi số 1: thiếu default khi chưa xử lý hết mọi trường hợp. Nếu bạn dùng switch biểu thức với kiểu có thể có giá trị nằm ngoài các case đã liệt kê (ví dụ với int hoặc String), trình biên dịch sẽ yêu cầu default. Với enum, nếu bạn không xử lý hết mọi giá trị, default cũng là bắt buộc.
Lỗi số 2: quên yield trong khối. Nếu dùng ngoặc nhọn cho case (cần thực hiện vài thao tác), đừng quên yield — nếu thiếu, trình biên dịch sẽ báo lỗi: "Missing yield statement".
Lỗi số 3: không khớp kiểu. Mọi nhánh của switch-biểu thức phải trả về các giá trị cùng một kiểu; nếu không, trình biên dịch sẽ không chấp nhận mã.
Lỗi số 4: trùng lặp giá trị case. Không được khai báo cùng một case hai lần — trình biên dịch sẽ báo lỗi ngay.
GO TO FULL VERSION