Gyakorlati alapok
Dönteni kell! (switch)
A fejezet eredményes feldolgozásához mindenképpen olvassuk át és értsük meg az előző, Dönteni kell! (if - else) című fejezet összefüggéseit!
A switch tulajdonképpen a többszörös elágazás lehetősége...
...amely során többféle (2-nél több) választási lehetőségből válogathatunk (némelyik programozási könyv összetett elágazásnak említi).
A switch-választás során szintén csak az egyik úton-ágon mehetünk tovább. Programozás-technikailag csakis az egyik ág kerül végrehajtásra, illetve ha semelyik ág nem teljesíti a feltételeket, akkor egy default nevű ág fut le. Egy switch-választás mindig helyettesíthető többszörös if else-ágakkal.
switch (bemeneti adat) {
case (1. feltétel): 1.választási ág; break;
case (2. feltétel): 2.választási ág; break;
case (3. feltétel): 3.választási ág; break;
case (4. feltétel): 4.választási ág; break;
default: Ha egyetlen feltétel sem teljesül; break;
}
Az utasítássor végén lévő break azt jelenti, hogy a feltétel teljesülése esetén a belső ciklus futása megszakad, a program a belső ciklusból kilép.
A switch a következő egyszerű és összetett adattípusokat képes bemeneti paraméterként fogadni:
-
char
-
byte
-
short
-
int
-
String
-
enum
-
Character
-
Byte
-
Short
-
Integer
A switch-szerkezetet hosszú, azaz többszörös és viszonylag egynemű, egzakt adatoknál és választási kényszereknél érdemes használnunk. Az alábbi, futtatható Java-kód például megmondja a hónapok sorszámából (int sorSzam) a hónap neveit, bár láthatjuk, hogy a legfontosabb, az adatbevitel mindig 5. hónapot, májust fog mutatni. Ezt még nem kezeltük le, hiszen még nem foglalkoztunk adatbevitel-implementációval. Ebből természetesen az is következik, hogy int sorSzam < 1 vagy int sorSzam > 12 esetén a default ág fut le, amely lényegében hibás adatbevitelt fog jelenteni.
public class Main {
public static void main(String[] args) {
int sorSzam = 5;
switch(sorSzam){
case 1: System.out.println("Január");
break;
case 2: System.out.println("Február");
break;
case 3: System.out.println("Március");
break;
case 4: System.out.println("Április");
break;
case 5: System.out.println("Május");
break;
case 6: System.out.println("Június");
break;
case 7: System.out.println("Július");
break;
case 8: System.out.println("Augusztus");
break;
case 9:
System.out.println("Szeptember"); break;
case 10: System.out.println("Október");
break;
case 11: System.out.println("November");
break;
case 12: System.out.println("December");
break;
default: System.out.println("Rossz
adatbevitel!"); break;
}
}
}
Végeredmény:
Május
A switch használatakor talán a legtipikusabb hiba, ha elfelejtjük kitenni a sorok végén lévő break utasítást. A hiba detektálása azonban egyszerű lesz, mert ekkor a kiválasztott ág, valamint az összes alatti lévő ág le fog futni:
public class Main {
public static void main(String[] args) {
int sorSzam = 5;
switch(sorSzam){
case 1: System.out.println("Január");
case 2: System.out.println("Február");
case 3: System.out.println("Március");
case 4: System.out.println("Április");
case 5: System.out.println("Május");
case 6: System.out.println("Június");
case 7: System.out.println("Július");
case 8: System.out.println("Augusztus");
case 9:
System.out.println("Szeptember");
case 10: System.out.println("Október");
case 11: System.out.println("November");
case 12: System.out.println("December");
default: System.out.println("Rossz
adatbevitel!");
}
}
}
Végeredmény:
Május
Június
Július
Augusztus
Szeptember
Október
November
December
Rossz adatbevitel!
Ha a switch-szerkezetben nem jelölünk ki minden ágat, akkor csak a megadott választási ág valamelyike fog lefutni. Adott például egy testsúlyminősítő algoritmus, amelyik nem mindegyik esetet minősít: int atlagSuly = 30
esetén a 40-hez tartozó minősítés egyaránt "Sovány".
public class Main {
public static void main(String[] args) {
int atlagSuly = 30;
switch(atlagSuly){
case 30:
case 40: System.out.println("Sovány"); break;
case 50:
case 60: System.out.println("Átlagos"); break;
case 70: System.out.println("Túlsúlyos"); break;
case 80:
case 90:
case 100: System.out.println("Kórosan túlsúlyos"); break;
default: System.out.println("Rossz adatbevitel!"); break;
}
}
}
Végeredmény:
Sovány
Tanítványi kérdés: Mi történik, ha átlagsúlynak nem 10-zel osztható számot írok be, például 36 (int atlagSuly = 36)?
A default ág fog lefutni, hiszen a case esetekben az nem szerepel. Természetesen kis trükközéssel elérhetjük, hogy a switch-szerkezetbe csakis 10-zel osztható számok kerüljenek (10, 20, 30, 40, stb.). A kód bemeneti pontja a bemenetiAdat nevű változó, ennek értéke van úgy manipulálva, hogy az atlagSuly változó már csak 10-zel osztható számokat kapjon. Mindeközben megpróbálom a switch-szerkezet eredeti struktúráját megtartani:
public class
Main {
public static void main(String[] args) {
String szamString = "";
int atlagSuly = 0;
int bemenetiAdat = 43;
if(bemenetiAdat < 10 && bemenetiAdat > 0){
bemenetiAdat = 10;
atlagSuly = bemenetiAdat;
}
else if(bemenetiAdat > 100){
bemenetiAdat = 100;
atlagSuly = bemenetiAdat;
}
else
atlagSuly = bemenetiAdat;
szamString = Integer.toString(bemenetiAdat);
int masodikDigit = Integer.parseInt(szamString.substring(1));
atlagSuly -= masodikDigit;
switch(atlagSuly){
case 10:
case 20:
case 30:
case 40:
System.out.println("Sovány"); break;
case 50:
case 60:
System.out.println("Átlagos"); break;
case 70:
System.out.println("Túlsúlyos"); break;
case 80:
case 90:
case 100:
System.out.println("Kórosan túlsúlyos"); break;
default:
System.out.println("Rossz adatbevitel!"); break;
}
}
}
Végeredmény:
Sovány
A switch-szerkezetnek vannak további mikrobeállítási szabályai.
Nyilvánvalóan nem adhatunk meg olyan típusú bemeneti vagy értékelő adatot, amelyet alapértelmezésben nem fogad el, például:
case 1,5: System.out.println(); break;
(lebegőpontos számot nem tud fogadni)
Kiértékelési értékben (case) csakis konstans, nem változó értékek adhatók meg. Az alábbi példában az 1. case nem konstans értékeket fogad (int a és b), a 2. már igen:
int a = 1;
int b = 2;
int c = 3;
switch(c){
case a + b: System.out.println(c); break; //Végeredmény: hiba, nem fog lefutni
case 1 + 2: System.out.println(c); break; //Végeredmény: 3
Megoldás a final szó használata, amely a változóértékeket konstanssá, nem változtathatóvá teszi (Ami a változót (és a többieket) változatlanná teszi: a final című fejezet). Programozási konvenció a konstans változók nagybetűs jelölése (például PI), ettől most az érthetőség kedvéért eltekintek.
final int a = 1;
final int b = 2;
int c = 3;
switch(c){
case a + b: System.out.println(c); break; //Végeredmény: 3
Egyes programozói vélekedések szerint a default ág mögé nem kell kitenni a break utasítást, hiszen ott egyébként is véget ér a kiértékelés. Ez igaz, a kód ilyen módon sem veszít funkcionalitásából. Ám az is igaz, hogy a hivatalos Java-dokumentáció ennek ellenére folyamatosan kiteszi.
Összefoglalva: ha a switch-szerkezet megengedett, egzakt, jól értelmezhető bemeneti adatot kap (és ez azt jelenti, hogy a lehetséges hibákat még a switch előtt le kell kezelnünk), akkor gyorsan és zökkenőmentesen képes a döntési mechanizmust lefuttatni. A szerkezet pontosan erre lett tervezve.