CodeGym /Các khóa học /JAVA 25 SELF /Biểu thức switch nâ...

Biểu thức switch nâng cao

JAVA 25 SELF
Mức độ , Bài học
Có sẵn

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;
}
Cú pháp biểu thức switch với ->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 Không
Rơi qua (fall-through) 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
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

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.

1
Khảo sát/đố vui
, cấp độ , bài học
Không có sẵn
Hằng số, enum và switch
Hằng số, enum và switch
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION