Spis treści
- Rozdział 4 - Instrukcje warunkowe
- Podstawy instrukcji warunkowych
- Operatory relacyjne
- Typ boolean
- Warunki instrukcji if
- Operatory warunkowe i operator logiczny !
- Tablica prawdy operatorów warunkowych
- Nawiasy i priorytety operatorów warunkowych
- Short-circuit evaluation
- Zagnieżdżanie instrukcji warunkowych
- Bloki kodu i zakresy zmiennych
- Instrukcja switch
- Trój-argumentowy operator logiczny
- Podsumowanie
- Pytania
- Zadania
Ważnym konceptem w programowaniu jest zakres widoczności i "życia" zmiennych i innych obiektów.
Spójrzmy na poniższy przykład – jaki będzie wynik działania tego programu?
public class UzyciePrzedDefinicja { public static void main(String[] args) { System.out.println("Liczba = " + liczba); int liczba = 5; } }
Powyższy program w ogóle się nie skompiluje – kompilator zgłosi błąd, ponieważ próbowaliśmy użyć zmiennej liczba zanim ją zdefiniowaliśmy w metodzie main:
Zmienna liczba istnieje dopiero od linii, w której zostanie zdefiniowana.
Spójrzmy na kolejny przykład – jaki będzie wynik Twoim zdaniem?
public class ZmiennaWBlokuIf { public static void main(String[] args) { int licznik = 9; int mianownik = 3; if (mianownik != 0) { double wynik = licznik / mianownik; } System.out.println("Wynik = " + wynik); } }
Program ponownie się nie skompiluje:
Kompilator protestuje, ponieważ nie wie czym jest "wynik".
Powodem jest fakt, że zmienną wynik utworzyliśmy w bloku instrukcji if. Zakres "życia" zmiennej wynik to jedynie blok instrukcji if – poza nim, zmienna ta przestaje istnieć i jest niedostępna w dalszej części kodu.
Spójrzmy na jeszcze jeden przykład:
Kolorami zaznaczone są fragmenty kodu, w których dostępne są poszczególne zmienne:
- Zmienna trzeciaLiczba dostępna jest jedynie w zagnieżdżonym bloku instrukcji if, ponieważ została w nim zdefiniowana – poza tym blokiem, zmienna trzeciaLiczba nie istnieje.
- Z kolei zmienna drugaLiczba dostępna jest zarówno w "głównym" bloku if, jak i w drugim, zagnieżdżonym w nim, bloku if. Zagnieżdżone bloki kodu mają dostęp do zmiennych zdefiniowanych wcześniej w zewnętrznych blokach, ale nie na odwrót.
- Zmienna liczba dostępna jest w całej metodzie main, od jej początku, aż do końca metody, ponieważ została zdefiniowana na samym jej początku.
W sekcji else głównej instrukcji warunkowej mamy dostęp jedynie do zmiennej liczba, ponieważ została zdefiniowana wcześniej w zewnętrznym bloku (którym jest ciało metody main). W sekcji else ani zmienna drugaLiczba, ani trzeciaLiczba, nie są znane, bo jeżeli doszło do wykonania kodu w sekcji else, to zmienne te nie zostały nigdy utworzone.
Bloki kodu w instrukcjach warunkowych¶
Na początku rozdziału o instrukcjach warunkowych dowiedzieliśmy się, że klamry przed i po instrukcjach przyporządkowanych do danej sekcji instrukcji warunkowej nie są wymagane, jeżeli do wykonania jest tylko jedna instrukcja – poniższy kod:
int x = 5; if (x > 0) { System.out.println("x jest wieksze od 0."); } else if (x < 0) { System.out.println("x jest mniejsze od 0."); } else { System.out.println("x jest rowne 0."); }
moglibyśmy zapisać także jako:
int x = 5; if (x > 0) System.out.println("x jest wieksze od 0."); else if (x < 0) System.out.println("x jest mniejsze od 0."); else System.out.println("x jest rowne 0.");
Wynika to z faktu, że w powyższym przykładzie sekcje warunkowe mają po jednej instrukcji do wykonania. Powinniśmy jednak zawsze stosować klamry { }, nawet wtedy, gdy instrukcja warunkowa ma przypisaną tylko jedną instrukcję do wykonania.
Zobaczmy w poniższym przykładzie-zagadce co może się stać, jeżeli zapomnimy otoczyć więcej niż jedną instrukcję w klamry:
import java.util.Scanner; public class IfBezBloku { public static void main(String[] args) { int licznik, mianownik; System.out.println("Podaj licznik:"); licznik = getInt(); System.out.println("Podaj mianownik:"); mianownik = getInt(); double wynik; if (mianownik != 0) wynik = licznik / mianownik; System.out.println("Wynik: " + wynik); } public static int getInt() { return new Scanner(System.in).nextInt(); } }
Jaki będzie wynik działania powyższego programu?
Program nawet się nie skompiluje! Zobaczymy komunikat, który widzieliśmy już w jednym z przykładów w poprzednim rozdziale, gdy poznawaliśmy zmienne:
Dlaczego zobaczyliśmy powyższy błąd? Nie otoczyliśmy obu linijek pod instrukcją if klamrami, więc do instrukcji if przyporządkowana jest tylko jedna instrukcja – nadanie wartości zmiennej wynik.
Jak wiemy z poprzedniego rozdziału, każdej zmiennej, zanim zostanie użyta, musi zostać nadana jakaś wartość.
W powyższym kodzie nadajemy zmiennej wynik wartość tylko w przypadku, gdy zmienna mianownik ma wartość różną od zera, więc istnieje taka ścieżka wykonania programu, w której zmiennej wynik nie zostałaby przypisana żadna wartość przed jej wypisaniem w linijce:
System.out.println("Wynik: " + wynik);
Kompilator Java jest na tyle "mądry", że jest w stanie wychwycić takie sytuacje i poinformować nas o nich jeszcze na etapie kompilacji.
Gdybyśmy nie zapomnieli o objęciu obu instrukcji (nadania wartości i jej wypisania) w blok za pomocą nawiasów klamrowych { }, to próba wypisania wartości odbyła by się tylko po uprzednim nadaniu jej wartości, dzięki czemu kod byłby poprawny, a kompilator by nie protestował.
Cześć,
Można prosić o komentarz z tym jak powinien wyglądać powyższy zapis (IfBezBloku.java)?
Cześć, masz na myśli jak ten program powinien wyglądać, żeby kompilował się bez błędu? Trzeba opakować obie instrukcje pod instrukcją warunkową
if
w nawiasy klamrowe:Dzięki 😉
Nie ma za co 🙂