Lekce 15 - Podmínky v Javě potřetí - Ternární výraz, propadávací switch
V předešlém cvičení, Řešené úlohy k 14. lekci Javy, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
V dnešním Java tutoriálu si představíme 2 další konstrukce, které souvisejí s podmínkami. Jedná se o oddechový tutoriál, kterým toto téma dokončíme.
Ternární operátor
Často se nám stává, že někde potřebujeme nastavit 2 různé hodnoty podle toho, zda platí nějaká podmínka.
Příklad - Výpis pohlaví
Představme si, že máme např. pohlaví uživatele uložené jako
boolean
(muž by byl true
) a my bychom ho chtěli
převést do textu. S dosavadními znalostmi bychom napsali asi takovýto
kód:
{JAVA_CONSOLE}
boolean muz = true; // nějaká proměnná udávající pohlaví
String nazevPohlavi;
if (muz) {
nazevPohlavi = "muž";
} else {
nazevPohlavi = "žena";
}
System.out.println(nazevPohlavi);
{/JAVA_CONSOLE}
Výstup programu je samozřejmě následující:
Konzolová aplikace
muž
Kód je poměrně upovídaný na to, že jen přepíná mezi dvěma hodnotami. Proto programovací jazyky často podporují tzv. ternární výraz.
Syntaxe ternárního výrazu
Pomocí tohoto operátoru můžeme získat hodnotu podle platnosti logického výrazu. Zapíšeme jej takto:
(podminka) ? plati : neplati
Podmínku vložíme většinou do závorky ()
, poté následuje
otazník ?
a 2 hodnoty, které se mají vrátit. Hodnoty jsou
oddělené dvojtečkou :
, první hodnota plati
se
vrátí, když podmínka platí. Druhá hodnota neplati
, když
podmínka neplatí. Jak snadné! Název operátoru je odvozený od toho, že má tři části
(podmínka, první hodnota a druhá hodnota), proto ternární.
Příklad - Výpis pohlaví pomocí ternárního výrazu
Pojďme si ternární operátor vyzkoušet na příkladu s pohlavím:
{JAVA_CONSOLE}
boolean muz = true; // nějaká proměnná udávající pohlaví
String nazevPohlavi = (muz) ? "muž" : "žena";
System.out.println(nazevPohlavi);
{/JAVA_CONSOLE}
Místo typu boolean
bychom mohli do závorky
samozřejmě napsat jakoukoli jinou podmínku, např.
(vek >= 18) ? "zletilý" : "nezletilý"
. V
případě jednoduchých výrazů můžeme závorku i vynechat.
Vnořování ternárních operátorů
Ternární operátory lze teoreticky zanořovat do sebe a tím reagovat i na tři a více hodnot. Nicméně ve většině případů zanořování spíše kód znepřehlední, vznikají totiž dlouhé nebo podivně zalomené řádky a není na první pohled vidět, jaká část se kdy spustí. Ukažme si, jak by se pomocí vnořování ternárních výrazů vyřešil výpis tří smajlíků:
{JAVA_CONSOLE}
String smajlik = ":)"; // nějaká proměnná udávající smajlíka
String nalada = (smajlik.equals(":)")) ? "veselý" : (smajlik.equals(":(")) ? "smutný" : "neznámý";
System.out.println(nalada);
{/JAVA_CONSOLE}
Pro příklad výše by bylo lepší vytvořit vlastní metodu, což si ale ukážeme až v navazujícím kurzu objektově orientovaného programování.
Konstrukce switch
s
propadáváním
S konstrukcí switch
jsme se již setkali v lekci Podmínky
(větvení). Dnes si ukážeme její další použití. Na rozdíl od
ternárního operátoru jde ale spíše o historickou funkčnost, pro kterou
dnes není moc rozumných využití. Stále je ale součástí standardní
gramatiky Javy a můžete na ni narazit v cizích zdrojových kódech.
Příklad - Čtvrtletí
Předpokládejme, že chceme podle měsíce v roce zjistit, jaké je
čtvrtletí. Pomocí bloků if
a else
by příklad
vypadal následovně:
{JAVA_CONSOLE}
int mesic = 2;
if (mesic >= 1 && mesic <= 3) {
System.out.println("Je první čtvrtletí.");
}
else if (mesic >= 4 && mesic <= 6) {
System.out.println("Je druhé čtvrtletí.");
}
else if (mesic >= 7 && mesic <= 9) {
System.out.println("Je třetí čtvrtletí.");
}
else if (mesic >= 10 && mesic <= 12) {
System.out.println("Je čtvrté čtvrtletí.");
}
{/JAVA_CONSOLE}
Jak ale použít konstrukci switch
pro takovýto příklad?
Možná by vás napadl následující zápis:
{JAVA_CONSOLE}
int mesic = 11;
switch (mesic) {
case 1:
System.out.println("Je první čtvrtletí.");
break;
case 2:
System.out.println("Je první čtvrtletí.");
break;
case 3:
System.out.println("Je první čtvrtletí.");
break;
case 4:
System.out.println("Je druhé čtvrtletí.");
break;
case 5:
System.out.println("Je druhé čtvrtletí.");
break;
case 6:
System.out.println("Je druhé čtvrtletí.");
break;
case 7:
System.out.println("Je třetí čtvrtletí.");
break;
case 8:
System.out.println("Je třetí čtvrtletí.");
break;
case 9:
System.out.println("Je třetí čtvrtletí.");
break;
case 10:
System.out.println("Je čtvrté čtvrtletí.");
break;
case 11:
System.out.println("Je čtvrté čtvrtletí.");
break;
case 12:
System.out.println("Je čtvrté čtvrtletí.");
break;
}
{/JAVA_CONSOLE}
Příklad funguje spolehlivě, problém však je, že jsme si tímto zápisem moc nepomohli. Podobnému repetitivnímu kódu bychom se vždy měli vyhýbat.
Propadávání
Zkusme to ještě jednou a využijme tzv. propadávání.
Pokud potřebujeme ve více blocích case
provádět stejný kód,
stačí tyto bloky vložit pod sebe a neukončovat každý blok pomocí
příkazu break
, ale celou skupinu bloku jedním příkazem
break
. Neukončené bloky tak propadnou a vykoná se kód
společný pro více bloků:
{JAVA_CONSOLE}
int mesic = 11;
switch (mesic) {
case 1:
case 2:
case 3:
System.out.println("Je první čtvrtletí.");
break;
case 4:
case 5:
case 6:
System.out.println("Je druhé čtvrtletí.");
break;
case 7:
case 8:
case 9:
System.out.println("Je třetí čtvrtletí.");
break;
case 10:
case 11:
case 12:
System.out.println("Je čtvrté čtvrtletí.");
break;
}
{/JAVA_CONSOLE}
Ukázka výstupu aplikace:
Konzolová aplikace
Je čtvrté čtvrtletí.
Tento zápis je již mnohem přehlednější. Konstrukce switch
má ovšem přidanou hodnotu v případě, kdy nemůžeme použít
větší/menší a jde o výčet hodnot, zde je to spíše redundantní kód
plný prázdných case
.
Java podporuje propadávání jak prázdných
case
, tak na rozdíl od jiných jazyků i case
s
dalším kódem. To je častá příčina nechtěných chyb (zapomenutých
break
) a velmi těžko se hledají.
Propadávání používejte v konstrukci switch
jen pokud k
němu máte dobrý důvod, nicméně je důležité, abyste jej uměli číst,
když na něj někde narazíte.
Vylepšená konstrukce
Od Javy verze 12 lze také využít vylepšenou konstrukci
switch
. Zápis výše by se dal ještě více zkrátit:
{JAVA_CONSOLE}
int mesic = 11;
switch (mesic) {
case 1, 2, 3 -> System.out.println("Je první čtvrtletí.");
case 4, 5, 6 -> System.out.println("Je druhé čtvrtletí.");
case 7, 8, 9 -> System.out.println("Je třetí čtvrtletí.");
case 10, 11, 12 -> System.out.println("Je čtvrté čtvrtletí.");
}
{/JAVA_CONSOLE}
V příští lekci, Cykly v Javě potřetí - do-while, break a continue, na nás čeká další syntaxe ohledně cyklů, na kterou můžeme narazit v cizích zdrojových kódech.