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
Instrukcje warunkowe if¶
- Instrukcje warunkowe służą do warunkowego wykonywania fragmentów kodu:
if (mianownik != 0) { System.out.println("Wynik: " + licznik / mianownik); } else { System.out.println("Mianownik nie moze byc = 0!"); }
- Instrukcje warunkowe sprawdzają prawdziwość pewnego warunku bądź warunków, tzn. sprawdzają, czy warunek jest prawdą (true) bądź fałszem (false) – w powyższym przykładzie:
- jeżeli mianownik jest różny od 0, to wykonana zostania instrukcja, która wypisuje na ekran wynik dzielenia zmiennej licznik przez mianownik.
- w przeciwnym razie, zostanie wykonana instrukcja, która wypisze na ekran komunikat o błędnej wartości zmiennej mianownik.
- Instrukcje warunkowe mogą mieć wiele sekcji – kolejne zapisujemy za pomocą else if.
- Instrukcje warunkowe mogą mieć jedną opcjonalną sekcję else, która wykonywana jest, gdy żaden z warunków nie będzie prawdziwy. Sekcja ta musi być zawsze na końcu instrukcji warunkowej.
- Instrukcje warunkowe mogą obejmować wiele instrukcji – należy je wtedy ująć w nawiasy klamrowe { }.
- Jeżeli do sekcji instrukcji warunkowej przypisana jest tylko jedna instrukcja, to nie musimy używać nawiasów klamrowych. Mimo tego, i tak powinniśmy stosować nawiasy klamrowe w takich przypadkach, by nasz kod był zgodny z ogólnie przyjętą w języku Java konwencją.
- Instrukcje warunkowe mogą być zagnieżdżone – wtedy klauzule else oraz else if odnoszą się do poprzedniego bloku instrukcji warunkowych.
if (operacja.equals("+")) { wynik = liczba1 + liczba2; } else if (operacja.equals("-")) { wynik = liczba1 - liczba2; } else if (operacja.equals("*")) { wynik = liczba1 * liczba2; } else if (operacja.equals("/")) { if (liczba2 != 0) { wynik = liczba1 / liczba2; } else { System.out.println("Mianownik nie moze byc zerem!"); } } else { System.out.println("Nieprawidlowa operacja!"); }
- Instrukcje przypisane do danej sekcji warunkowej powinny mieć wcięcia (powinny być wysunięte o np. dwie spacje), jak w przykładzie powyżej, dotyczącym zagnieżdżonych instrukcji if. Instrukcje w zewnętrznej instrukcji if mają pojedyncze wcięcie. W zagnieżdżonej instrukcji if, przyporządkowane do niej instrukcje wcięte są o kolejny poziom.
- Warunki sprawdzane w instrukcji if muszą zawsze dawać w wyniku jedną z dwóch wartości: prawda (true) bądź fałsz (false).
- Warunki sprawdzane są zawsze w kolejności od pierwszego do ostatniego. Jeżeli pierwszy warunek nie zostanie spełniony, to sprawdzony będzie kolejny (o ile istnieje kolejna sekcja else if) itd., aż znaleziony zostanie warunek, który będzie miał wartość true, lub żaden z warunków nie będzie miał wartości true. W takim przypadku, wykonane zostaną instrukcje pod sekcją else, o ile jest obecna.
Operatory relacyjne i typ boolean¶
- Operatory relacyjne to operatory dwuargumentowe, które porównują wartości swoich argumentów, i zwracają jedną z wartości: true bądź false.
- Do dyspozycji mamy następujące operatory relacyjne:
- < mniejsze niż
- > większe niż
- <= mniejsze bądź równe
- >= większe bądź równe
- == równe (nie mylić z operatorem przypisania =)
- != nierówne
- Należy uważać, by nie pomylić operatora porównującego wartości ( == ) z operatorem przypisania ( = ).
- Zmienne typu boolean mogą przechowywać tylko jedną z dwóch możliwych wartości – true bądź false.
- Zmienne typu boolean przydają się do przechowywania informacji typu prawda/fałsz, np. czyUzytkownikZalogowany, czyLiczbaParzysta, czyZakonczycProgram.
- Wartość wyrażenia, które wykorzystuje operator relacyjny, ma zawsze wartość true lub false – dokładnie takie same wartości, jakie mogą przechowywać zmienne typu boolean – możemy więc przypisać do zmiennej typu boolean wynik takiego wyrażenia:
int liczba = 5; // przypisujemy do zmiennej wynik ponizszego porownania boolean czyParzysta = liczba % 2 == 0;
- Zmienna typu boolean może być użyta jako warunek w instrukcji warunkowej if:
boolean czyPadaDeszcz = false; if (czyPadaDeszcz) { System.out.println("Wez parasol!"); } else { System.out.println("Zostaw parasol w domu."); }
- Jeżeli chcemy porównać ze sobą zmienne typu String lub zmienną typu String z łańcuchem tekstowym (zapisanym w cudzysłowach " "), należy skorzystać z metody equals klasy String – nie powinniśmy porównywać stringów za pomocą operatora ==, ponieważ wynik będzie inny, niż się spodziewamy!
- Metoda equals zwraca true, jeżeli przekazany do niej jako argument ciąg znaków jest taki sam, jak zmienna typu String, na rzecz której tą metodę wywołaliśmy. W przeciwnym razie zwracana jest wartość false. Uwaga: małe i wielkie litery są rozróżniane! Poniższy kod spowoduje wypisanie na ekran komunikatu "Rozne", ponieważ wielkość znaków jest różna w zmiennej typu String oraz w porównywanej do niej wartości "WITAJ":
String tekst = "Witaj"; if (tekst.equals("WITAJ")) { System.out.println("Takie same"); } else { System.out.println("Rozne"); }
Operatory warunkowe¶
- Aby zapisać bardziej skomplikowany warunek w instrukcji if, łączymy ze sobą kolejne warunki przy użyciu operatora && (and) bądź || (lub). Warunki mogą być dowolnie złożone i używać każdego z operatorów dowolną liczbę razy.
- Tablica prawdy to tabela informująca, jaką wartość ma wyrażenie, w którym wykorzystywany jest pewny operator z podanymi mu argumentami.
- Tabela prawdy możliwych wyników zastosowania operatorów &&, ||, oraz !
x | y | x || y | x && y | !x |
---|---|---|---|---|
false | false | false | false | true |
true | false | true | false | false |
false | true | true | false | true |
true | true | true | true | false |
- Przykład dla wartości a = 0 i b = 100:
a > 0 | b >= 100 | a > 0 || b >= 100 |
a > 0 && b >= 100 |
!(a > 0) | !(b >= 100) |
---|---|---|---|---|---|
false | true | true | false | true | false |
- Operator && ma wyższy priorytet, niż operator || – poniższy kod:
x > 0 && y > 0 || z > 0
- jest równoznaczny z poniższym zapisem, który wykorzystuje nawiasy w celu zwiększenia czytelności:
(x > 0 && y > 0) || z > 0
- Moglibyśmy zmienić kolejność wykonywania porównań w powyższym wyrażeniu stosując nawiasy:
x > 0 && (y > 0 || z > 0)
- Jeżeli mamy kilka wyrażeń w warunku i korzystamy z różnych operatorów (&& i ||), to warto stosować nawiasy w celu zwiększenia czytelności kodu.
- Operator logiczny ! to jednoargumentowy operator, logiczne zaprzeczenie (not), który oczekuje jako argumentu wartości true bądź false, i zwraca wartość przeciwną, tzn. dla argumentu true zwraca wartość false, a dla false – zwraca true.
- Operatora logicznego ! możemy użyć w celu odwrócenia wartości w instrukcji if – w poniższym przykładzie, komunikat "Sloneczna pogoda." zostanie wyświetlony, gdy wartość czyPadaDeszcz będzie równa false, bo zaprzeczenie czyPadaDeszcz (!czyPadaDeszcz) będzie miało wartość true:
boolean czyPadaDeszcz = true; if (!czyPadaDeszcz) { System.out.println("Sloneczna pogoda."); } else { System.out.println("Zostaje w domu!"); }
- Operatora logicznego ! możemy używać także do zaprzeczania bardziej skomplikowanych wyrażeń:
int a, b; a = 5; b = -10; if (!(a > 0 && b > 0)) { System.out.println("Niepoprawne dane."); } else { System.out.println("Pola prostokata = " + a * b); }
- Dodatkowo, operatora logicznego ! możemy także użyć, by zamienić wartość zmiennej typu boolean na przeciwną wartość:
boolean czyPadaDeszcz = false; // zmiennej czyPadaDeszcz zostanie przypisana wartosc true czyPadaDeszcz = !czyPadaDeszcz;
- Pisząc złożone instrukcje warunkowe, często jesteśmy w stanie odpowiedzieć na pytanie, czy całe wyrażenie ma szansę być prawdą bądź nie jeszcze zanim obliczymy każde z wyrażeń, które na ten warunek się składa – w poniższym przykładzie:
if (a <= 0 || b <= 0) { System.out.println("Nieprawidlowe dane."); } else { System.out.println("Pole wynosi " + a * b); }
- W powyższej instrukcji warunkowej wystarczy, że pierwsze wyrażenie, a <= 0 , będzie prawdą, aby całe wyrażenie a <= 0 || b <= 0 miało wartość true. W takim przypadku, obliczanie wartości wyrażenia b <= 0 nie ma sensu, bo i tak wiemy już, że niezależnie od wartości wyrażenia b <= 0, całe wyrażenie, a <= 0 || b <= 0 będzie miało wartość true (ponieważ operatorowi || wystarczy jeden argument o wartości true, aby całe wyrażenie miało wartość true).
- Dzięki funkcjonalności zwanej short-circuit evaluation, nasz program nie będzie zawsze sprawdzał wszystkich warunków, jeżeli jest w stanie wcześniej jednoznacznie wyznaczyć końcową wartość danego wyrażenia. Nie musimy nic robić, aby z tego funkcjonalności korzystać – jest ona po prostu automatycznie stosowana przez Maszynę Wirtualną Java, która wykonuje kod naszego programu. Funkcjonalność ta działa zarówno dla operatora ||, jak i operatora &&.
Bloki kodu i zakres zmiennych¶
- Blok kodu to fragment zawarty w nawiasach klamrowych.
- Zmienna zdefiniowana np. w bloku instrukcji if będzie niedostępna, gdy wyjdziemy poza zakres bloku tej instrukcji if – poniższy kod się nie skompiluje, ponieważ zmienna wynik nie istnieje poza blokiem if, w którym została zdefiniowana – kompilator zgłosi błąd w linijce System.out.println("Wynik = " + wynik); ponieważ w tym miejscu nie istnieje już żadna zmienna o nazwie wynik:
public static void main(String[] args) { int licznik = 9; int mianownik = 3; if (mianownik != 0) { double wynik = licznik / mianownik; } // ponizsza linia spowoduje blad kompilacji! // nie ma tu juz zadnej zmiennej o nazwie wynik System.out.println("Wynik = " + wynik); }
Instrukcja switch¶
- Instrukcja switch służy do porównania wartości zmiennej z wylistowanymi stałymi wartościami – wykonane zostaną te instrukcje, które są skojarzone z dopasowaną wartością:
int liczba = 10; switch (liczba) { case 10: System.out.println("liczba == 10"); break; case 100: System.out.println("liczba == 100"); break; default: System.out.println("liczba ma inna wartosc"); }
- Instrukcja switch może mieć klauzulę default, która zostania wykonana, jeżeli żaden z warunków nie będzie spełniony.
- Słowa kluczowe break powinny zostać użyte w każdym bloku case, jeżeli nie chcemy, aby wykonane zostały instrukcje z kolejnych bloków case, gdy porównywana wartość zostanie dopasowana do któregoś z nich. W poniższym przykładzie nie ma instrukcji break, przez co, po dopasowanie wartości 10 do zmiennej liczba, wykonywane są wszystkie operacje pod spodem:
int liczba = 10; switch (liczba) { case 10: System.out.println("liczba == 10"); case 100: System.out.println("liczba == 100"); default: System.out.println("liczba ma inna wartosc"); }
liczba == 10 liczba == 100 liczba ma inna wartosc - Instrukcji switch można używać jedynie z następującymi typami:
- byte i Byte, short i Short, char i Character, int i Integer,
- String
- enum
Trój-argumentowy operator logiczny¶
- Operator ten to skrócona forma prostych instrukcji warunkowych – jego składnia jest następująca:
wyrazenieLogiczne ? wyrazenieGdyPrawda : wyrazenieGdyFalsz
- W poniższym przykładzie przypiszemy do zmiennej wartoscAbsolutna wartość x, jeżeli x jest liczbą dodatnią. W przeciwnym razie, przypiszemy do zmiennej wartoscAbsolutna przeciwieństwo wartości zmiennej x:
int x = 5; int wartoscAbsolutna; wartoscAbsolutna = x > 0 ? x : -x;