Kiểm soát Vòng Lặp với continue, break và Nhãn trong Java

1. Ứng dụng của continue và break trong câu lệnh switch kết hợp với vòng lặp for

Trong lập trình Java, các từ khóa continuebreak là những công cụ mạnh mẽ để điều khiển luồng thực thi bên trong các vòng lặp. Khi được sử dụng trong một câu lệnh switch nằm trong một vòng lặp for, chúng có những tác động khác nhau đến quá trình lặp. Hãy xem xét ví dụ sau để hiểu rõ hơn về cách chúng hoạt động:

public class LoopControlExamples {

    public static void main(String[] args) {
        int accumulatedSum = 0;
        System.out.println("--- Bắt đầu minh họa continue/break trong switch và for ---");

        for (int iterationCount = 1; iterationCount < 5; iterationCount++) {
            System.out.println("\n> Khởi đầu vòng lặp for thứ: " + iterationCount + ", Tổng hiện tại: " + accumulatedSum);

            switch (iterationCount) {
                case 1:
                    accumulatedSum += 2;
                    // Fall-through to case 2 as there's no break
                case 2:
                    accumulatedSum += 4;
                    System.out.println("  [Case " + iterationCount + "] Gặp LỆNH CONTINUE. Thoát khỏi switch và bỏ qua phần còn lại của VÒNG LẶP FOR hiện tại.");
                    System.out.println("  Tổng sau khi gặp continue: " + accumulatedSum);
                    continue; // Chuyển sang lần lặp tiếp theo của vòng for
                case 3:
                    accumulatedSum += 16;
                    System.out.println("  [Case " + iterationCount + "] Gặp LỆNH BREAK. Thoát khỏi switch, nhưng TIẾP TỤC thực thi trong vòng lặp for.");
                    System.out.println("  Tổng sau khi gặp break: " + accumulatedSum);
                    break; // Thoát khỏi switch, tiếp tục thực thi các lệnh sau switch trong vòng for
                default:
                    accumulatedSum += 4;
                    System.out.println("  [Case Mặc định] Không khớp case nào. Tổng: " + accumulatedSum);
                    // Không có break/continue ở đây, sẽ tiếp tục thực thi sau switch
            }
            System.out.println("  <-- ĐANG TIẾP TỤC thực thi CÁC LỆNH CÒN LẠI trong vòng for (chỉ hiển thị khi có break hoặc default) -->");
        }
        System.out.println("\n--- Vòng lặp for đã kết thúc. Tổng cuối cùng: " + accumulatedSum + " ---");
    }
}

Giải thích luồng thực thi:

  • Khi iterationCount là 1:
    • accumulatedSum trở thành 2 (từ case 1), sau đó 6 (từ case 2 do fall-through).
    • Gặp continue trong case 2. Lệnh này ngay lập tức kết thúc lần lặp hiện tại của vòng for (tức là không chạy dòng "ĐANG TIẾP TỤC thực thi..." bên dưới switch) và chuyển sang lần lặp tiếp theo của for.
    • iterationCount tăng lên 2.
  • Khi iterationCount là 2:
    • accumulatedSum trở thành 10 (6 + 4 từ case 2).
    • Gặp continue trong case 2. Tương tự như trên, vòng for nhảy sang lần lặp kế tiếp.
    • iterationCount tăng lên 3.
  • Khi iterationCount là 3:
    • accumulatedSum trở thành 26 (10 + 16 từ case 3).
    • Gặp break trong case 3. Lệnh này chỉ thoát khỏi khối switch. Chương trình sau đó tiếp tục thực thi các lệnh ngay sau switch bên trong vòng for.
    • Dòng "ĐANG TIẾP TỤC thực thi..." được hiển thị.
    • Vòng for hoàn tất lần lặp này và iterationCount tăng lên 4.
  • Khi iterationCount là 4:
    • Không khớp với case 1, 2, hay 3, nên chạy khối default.
    • accumulatedSum trở thành 30 (26 + 4 từ default).
    • Không có break hay continue trong default, nên thực thi các lệnh sau switch.
    • Dòng "ĐANG TIẾP TỤC thực thi..." được hiển thị.
    • Vòng for hoàn tất lần lặp này và iterationCount tăng lên 5.
  • Vòng for kết thúc vì iterationCount không còn nhỏ hơn 5. Tổng cuối cùng là 30.

Điều quan trọng cần nhớ là continue sẽ bỏ qua phần còn lại của lần lặp vòng lặp chứa nó, trong khi break chỉ thoát khỏi khối switch hoặc vòng lặp chứa nó (nếu không có switch).

2. Sử dụng nhãn (Labels) với break và continue trong Java

Mặc dù Java không có câu lệnh goto theo nghĩa truyền thống như C/C++, nó cung cấp cơ chế nhãn (labels) để điều khiển luồng của các câu lệnh breakcontinue trong các vòng lặp lồng nhau. Điều này cho phép chúng ta thoát hoặc bỏ qua các lần lặp của một vòng lặp bên ngoài từ bên trong một vòng lặp lồng sâu hơn.

public class LabeledLoopControl {

    public static void main(String[] args) {
        System.out.println("--- Bắt đầu minh họa Labeled Loop Control trong Java ---");
        int innerLoopVariable = 0;

        outerLoop: // Định nghĩa nhãn cho vòng lặp ngoài
        for (int outerLoopVariable = 0; ; outerLoopVariable++) { // Vòng lặp ngoài vô hạn
            System.out.println("\n> Bắt đầu VÒNG LẶP NGOÀI, lượt: " + outerLoopVariable);

            innerLoop: // Định nghĩa nhãn cho vòng lặp trong
            for (; innerLoopVariable < 10; innerLoopVariable++) { // Vòng lặp trong, điều khiển bởi innerLoopVariable
                System.out.println("  > Vòng lặp trong: outer=" + outerLoopVariable + ", inner=" + innerLoopVariable);

                if (innerLoopVariable == 2) {
                    System.out.println("    [inner=" + innerLoopVariable + "] Gặp CONTINUE (không nhãn). Bỏ qua phần còn lại của vòng lặp trong hiện tại.");
                    continue; // Chỉ bỏ qua phần còn lại của 'innerLoop'
                }

                if (innerLoopVariable == 3) {
                    innerLoopVariable++; // Tăng biến trước khi break để khớp logic gốc và đầu ra
                    System.out.println("    [inner=" + (innerLoopVariable -1) + "] Gặp BREAK (không nhãn). Thoát khỏi vòng lặp trong.");
                    break; // Thoát khỏi 'innerLoop', tiếp tục 'outerLoop'
                }
                
                // Vòng lặp thứ ba lồng sâu hơn để minh họa 'continue innerLoop'
                for (int deepestLoopVariable = 0; deepestLoopVariable < 5; deepestLoopVariable++) {
                    if (deepestLoopVariable == 3) {
                        System.out.println("    [deep=" + deepestLoopVariable + "] Gặp CONTINUE innerLoop. Nhảy tới lần lặp TIẾP THEO của vòng lặp trong.");
                        continue innerLoop; // Nhảy tới lần lặp tiếp theo của vòng 'innerLoop'
                    }
                }

                if (innerLoopVariable == 7) {
                    innerLoopVariable++; // Tăng biến trước khi continue để khớp logic gốc và đầu ra
                    System.out.println("    [inner=" + (innerLoopVariable -1) + "] Gặp CONTINUE outerLoop. Nhảy tới lần lặp TIẾP THEO của vòng lặp ngoài.");
                    continue outerLoop; // Nhảy tới lần lặp tiếp theo của vòng 'outerLoop'
                }

                if (innerLoopVariable == 8) {
                    System.out.println("    [inner=" + innerLoopVariable + "] Gặp BREAK outerLoop. THOÁT HOÀN TOÀN khỏi vòng lặp ngoài.");
                    break outerLoop; // Thoát hoàn toàn khỏi 'outerLoop'
                }

                System.out.println("  <-- Tiếp tục thực thi trong vòng lặp trong (sau vòng lặp sâu nhất) -->");
            }
            System.out.println("Kết thúc vòng lặp trong. Đang TIẾP TỤC thực thi trong vòng lặp ngoài: " + outerLoopVariable);
        }
        System.out.println("\n--- Tất cả các vòng lặp đã kết thúc ---");
    }
}

Giải thích luồng thực thi với nhãn:

  • outerLoop: for (...)innerLoop: for (...): Đây là cách định nghĩa nhãn. Nhãn được đặt ngay trước câu lệnh vòng lặp mà nó áp dụng.
  • if (innerLoopVariable == 2) { continue; }:
    • Khi innerLoopVariable là 2, lệnh continue này chỉ bỏ qua phần còn lại của lần lặp hiện tại của vòng innerLoop.
    • innerLoopVariable tăng lên 3, và vòng innerLoop tiếp tục với lần lặp mới.
  • if (innerLoopVariable == 3) { innerLoopVariable++; break; }:
    • Khi innerLoopVariable là 3, lệnh break này thoát khỏi vòng innerLoop.
    • Chương trình tiếp tục thực thi các lệnh ngay sau innerLoop, tức là in ra "Kết thúc vòng lặp trong..." và sau đó outerLoopVariable tăng lên.
  • if (deepestLoopVariable == 3) { continue innerLoop; }:
    • Khi deepestLoopVariable là 3, lệnh continue innerLoop sẽ bỏ qua phần còn lại của lần lặp hiện tại của vòng innerLoop (và cả deepestLoop), đồng thời nhảy đến lần lặp tiếp theo của innerLoop.
    • Điều này có nghĩa là mọi lệnh sau khối deepestLoop trong lần lặp hiện tại của innerLoop sẽ bị bỏ qua.
  • if (innerLoopVariable == 7) { innerLoopVariable++; continue outerLoop; }:
    • Khi innerLoopVariable là 7, lệnh continue outerLoop sẽ bỏ qua phần còn lại của lần lặp hiện tại của vòng outerLoop và nhảy đến lần lặp tiếp theo của outerLoop.
    • Lưu ý rằng innerLoopVariable được tăng lên trước khi continue outerLoop để đảm bảo vòng lặp ngoài tiến triển và tránh lặp vô hạn với cùng giá trị innerLoopVariable.
  • if (innerLoopVariable == 8) { break outerLoop; }:
    • Khi innerLoopVariable là 8, lệnh break outerLoop sẽ thoát hoàn toàn khỏi vòng outerLoop (và tất cả các vòng lặp lồng bên trong nó).
    • Chương trình chuyển đến câu lệnh ngay sau toàn bộ khối outerLoop.

Việc sử dụng nhãn là cần thiết trong Java khi bạn cần thoát hoặc bỏ qua các lần lặp của một vòng lặp bên ngoài từ một vòng lặp lồng sâu hơn. Nếu không có nhãn, breakcontinue mặc định chỉ tác động đến vòng lặp gần nhất.

Thẻ: Java continue break LabeledStatements LoopControl

Đăng vào ngày 1 tháng 6 lúc 00:36