Menu

Pętla while w Javie: składnia, do-while i typowe błędy

Pętla while w Javie w praktyce: while sprawdzające warunek na początku, do-while wykonujące się co najmniej raz, wczytywanie danych do wartości wartowniczej, break i continue oraz unikanie pętli nieskończonych.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Gdy nie masz licznika

Pętla for opiera się na liczniku, który ustawiasz na starcie. Ale wiele pętli nie ma wyraźnej liczby powtórzeń: czytaj wiersze, aż skończy się plik, pytaj o hasło, aż będzie poprawne, dziel liczbę na pół, aż dojdzie do 1. W takich przypadkach naturalnym wyborem jest pętla while: po prostu powtarza, dopóki warunek pozostaje prawdziwy.

Pętla while sprawdza warunek przed każdym przebiegiem, także przed pierwszym. Jeśli warunek od początku jest fałszywy, ciało nie wykona się ani razu.

Najpierw sprawdzany jest warunek count > 0; jeśli jest prawdziwy, wykonuje się ciało; potem pętla wraca i sprawdza go znowu. Linia count-- jest tym, co w końcu sprawia, że warunek staje się fałszywy: usuń ją, a pętla będzie działać w nieskończoność.

Budowa pętli while

Porównaj ją z trzyczęściową pętlą for, którą już znasz. Pętla while rozdziela te trzy zadania: przygotowanie robisz przed pętlą, warunek trafia do nawiasów, a aktualizacja mieszka wewnątrz ciała.

int i = 0;              // inicjalizacja, przed pętlą
while (i < 5) {         // warunek, sprawdzany w każdym przebiegu
    System.out.println(i);
    i++;                // aktualizacja, o której musisz pamiętać samodzielnie
}

Ta ostatnia część to haczyk. W pętli for aktualizacja stoi tuż obok warunku, więc trudno o niej zapomnieć. W pętli while to po prostu kolejna instrukcja w ciele, a najczęstszy błąd to jej pominięcie i zawieszenie programu.

do-while: ciało wykonuje się co najmniej raz

Czasem ciało musi wykonać się raz, zanim w ogóle zdecydujesz, czy powtarzać. Pętla do-while sprawdza warunek na dole, więc ciało zawsze wykonuje się przynajmniej jeden raz:

Musisz co najmniej raz poprosić o dane i je wczytać, zanim dowiesz się, czy są poprawne, i dokładnie to daje do-while. Zwróć uwagę na średnik po while (...): jest wymagany, a jego brak to częsty błąd kompilacji.

Różnicę względem zwykłego while widać wyraźnie, gdy warunek od początku jest fałszywy:

Wypisze się tylko do-while body. Pętla while całkowicie pomija ciało, bo x < 5 było fałszywe już przed pierwszym sprawdzeniem.

Pętla do wartości wartowniczej

Klasyczne zastosowanie while to wczytywanie danych aż do specjalnej wartości "stop", czyli wartownika (sentinel). Nie ma tu licznika; po prostu działasz dalej, aż dane każą skończyć:

Wzorzec wygląda tak: wczytaj raz przed pętlą, potem wczytuj ponownie na końcu każdego przebiegu. Dzięki temu warunek zawsze sprawdza świeże dane. Jeśli zapomnisz o drugim wczytaniu w ciele, value nigdy się nie zmieni i dostaniesz pętlę nieskończoną.

break i continue w pętlach while

break i continue działają tu tak samo jak w pętli for. break natychmiast opuszcza pętlę; continue od razu wraca do sprawdzenia warunku, pomijając resztę bieżącego przebiegu:

Ten kod wypisuje 1 3 5 7 9. while (true) celowo nigdy nie zatrzymuje się samo: break jest jedynym wyjściem. Uważaj na continue w pętli while: ponieważ aktualizacja jest częścią ciała, powrót na górę przez continue, zanim przesuniesz licznik, to cichy sposób na zawieszenie pętli. W powyższym przykładzie n++ wykonuje się najpierw, więc jest bezpiecznie.

Uważaj na pętle nieskończone

Warunek musi w końcu stać się fałszywy, a to zależy wyłącznie od tego, czy coś w ciele się zmienia. Dwaj typowi winowajcy to zapomniana aktualizacja i aktualizacja w złą stronę:

int i = 0;
while (i < 5) {
    System.out.println(i);   // i nigdy się nie zmienia -> działa w nieskończoność
}
int i = 0;
while (i != 10) {
    i += 3;   // 0, 3, 6, 9, 12... przeskakuje 10 -> działa w nieskończoność
}

Pierwsza pętla się zawiesza, bo i nigdy nie jest aktualizowane. Druga, bo licznik przeskakuje dokładnie tę wartość, której szuka warunek: gdy krok może nie trafić idealnie, wybieraj < lub <= zamiast !=. while (true) jest w porządku, jeśli ma zagwarantowany break; przypadkowe to po prostu błąd.

Dalej: pętla for-each

Pętla while to właściwe narzędzie, gdy powtarzasz coś do zmiany warunku i nie masz wyraźnej liczby powtórzeń. Ale gdy chcesz po prostu odwiedzić każdy element tablicy albo listy, bez indeksu i bez warunku do pilnowania, jest coś jeszcze czytelniejszego: rozszerzona pętla for-each. O niej jest następna strona.

Najczęściej zadawane pytania

Czym różni się while od do-while w Javie?

Pętla while sprawdza warunek przed pierwszym przebiegiem, więc ciało może nie wykonać się ani razu. Pętla do-while najpierw wykonuje ciało raz, a dopiero potem sprawdza warunek na dole, więc zawsze wykonuje się co najmniej raz. Używaj do-while, gdy praca musi się odbyć, zanim zdecydujesz, czy powtarzać (np. prośba o dane, a potem ich sprawdzenie).

Kiedy w Javie użyć pętli while zamiast for?

Użyj pętli while, gdy nie masz wyraźnego licznika i chcesz po prostu powtarzać aż do zmiany jakiegoś warunku: wczytywać dane, dopóki użytkownik nie wpisze quit, odpytywać, aż wartość będzie gotowa, albo przetwarzać kolejkę, aż będzie pusta. Po pętlę for sięgaj, gdy znasz liczbę iteracji albo masz oczywisty indeks do liczenia.

Jak zatrzymać nieskończoną pętlę while w Javie?

Upewnij się, że coś w ciele pętli w końcu sprawi, że warunek stanie się fałszywy (zmniejszenie licznika, przesunięcie wskaźnika, ustawienie flagi). W zamierzonej pętli while (true) umieść w środku break zabezpieczony przez if. Jeśli pętla się zawiesza, zwykle przyczyną jest brak aktualizacji zmiennej, od której zależy warunek.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ