Programmeren in Java/Lussen
Tot nu toe heb je geprogrammeerd door regelt per regel of statement per statement te zeggen wat je wilt doen. Je zal echter zien dat je regelmatig een aantal keer exact hetzelfde wilt doen achter elkaar. Stel dat je een programma schrijft die van één tot vijf moet tellen en dit ook moet afprinten. Je zou dan het volgende kunnen doen.
public class Main {
public static void main(String[] args) {
int number = 1;
System.out.println("Getal: " + number);
number++;
System.out.println("Getal: " + number);
number++;
System.out.println("Getal: " + number);
number++;
System.out.println("Getal: " + number);
number++;
System.out.println("Getal: " + number);
}
}
Dit zal correct werken, maar je ziet dat je veel dubbele code hebt en wat als je niet tot vijf wilt tellen maar tot tien? Dan zou je op deze manier nog eens 5 keer de waarde moet verhogen en afprinten. Gelukkig bestaat er in Java, en ook de meeste andere programmeertalen, zoiets als lussen. Lussen, ofwel in het Engels loops, is een manier om stukjes code te herhalen. Niet alleen dat, maar je kunt ook voorwaarden meegeven om de lus te stoppen. Je zou dan bijvoorbeeld een lus kunnen schrijven om bovenstaand voorbeeld te vervangen. Waarbij je de code geeft die de lus moet herhalen, in dit voorbeeld het verhogen van number en het uitprinten ervan. Daarnaast kun je ook zeggen dat de lus moet stoppen als het getal als waarde vijf heeft bereikt.
Er zijn verschillende soorten lussen in dit hoofdstuk gaan we de while, de do ... while en de for bespreken.
While
[bewerken]De while-lus is de eenvoudigste van de lussen om te gebruiken en te begrijpen en ziet er als volgt uit.
while (<booleaanse uitdrukking>) {
// De code die herhaaldelijk moet worden uitgevoerd door de lus.
}
De while begint met het sleutelwoord while gevolgd door haakjes die een booleaanse uitdrukking bevat, gevolgd door een code block die herhaaldelijk kan worden uitgevoerd door de lus. De code block zal continue worden uitgevoerd zolang de booleaanse uitdrukking die de while bevat als resultaat true heeft en stopt zodra de booleaanse uitdrukking als resultaat false wordt.
Als we terug kijken naar ons oorspronkelijk code dan wouden we tellen van één tot en met vijf. We hebben een variable van het type int die we declareren met de waarde één. We printen het op het scherm en tellen er één bij, dit doen we tot we het getal vijf op het scherm hebben gedrukt. Wat we hier moeten uit halen voor een lus te maken is enerzijds de code die de lus moet herhalen en anderzijds de voorwaarde om de lus te laten herhalen. De code die we herhalen is:
System.out.println("Getal: " + number);
number++;
En dan is er nog de voorwaarde om de code te herhalen in de vorm van een booleaanse uitdrukking. We willen dat de lus draait zolang het nog géén vijf op het scherm heeft getoond. Dit kunnen we doen door bijvoorbeeld de uitdrukking number < 6. De lus zal dus blijven draaien tot de variabele number vijf heeft bereikt, want zodra het zes is stopt de lus en moet de codeblok niet meer worden uitgevoerd. Als je dat samen brengt krijg je het volgende.
public class Main {
public static void main(String[] args) {
int number = 1;
while (number < 6) {
System.out.println("Getal: " + number);
number++;
}
}
}
Dit zal het volgende resultaat geven.
Getal: 1 Getal: 2 Getal: 3 Getal: 4 Getal: 5
Will je dan dat er tot en met het getal 10 wordt geprint moet je gewoon de booleaanse uitdrukking aanpassen naar bijvoorbeeld number < 11.
Do ... While
[bewerken]De do ... while-lus is de volgende soort lus die we gaan bespreken en ziet er zo uit.
do {
// De code die herhaaldelijk moet worden uitgevoerd door de lus.
} while (<booleaanse uitdrukking>);
Zoals je ziet begint de lus met het sleutelwoord do, gevolgd door een codeblok, met daarna while en een bijhorende booleaanse uitdrukking. Als we dezelfde code in de blok zetten als van onze vorige while-lus en dezelfde uitdrukking dan krijgen we het volgende.
public class Main {
public static void main(String[] args) {
int number = 1;
do {
System.out.println("Getal: " + number);
number++;
} while (number < 6);
}
}
Dan krijgen we het volgend resultaat.
Getal: 1 Getal: 2 Getal: 3 Getal: 4 Getal: 5
Hetzelfde resultaat al de vorige while. Dus wat is het verschil? Het verschil is dat bij een do ... while de code in de codeblok sowieso minstens éénmaal wordt uitgevoerd ongeacht wat het resultaat is van de booleaanse uitdrukking. De codeblok wordt als eerst uitgevoerd en pas daarna wordt er gekeken of de lus zich nog moet herhalen. Om dit aan te tonen kun je een booleaanse uitdrukking gebruiken die sowieso false geeft als resultaat.
public class Main {
public static void main(String[] args) {
int number = 1;
do {
System.out.println("Getal: " + number);
number++;
} while (number < 0);
}
}
Dit geeft als resultaat.
Getal: 1
For
[bewerken]Dan is er ook nog de for-lus en die ziet er als volgt uit.
for (<statement 1>; <statement 2>; <statement 3>) {
// De code die herhaaldelijk moet worden uitgevoerd door de lus.
}
In tegenstelling tot de while en de do ... while-lus, heeft de for drie statements nodig:
- Statement 1: Een declaratie van de variabelen die geldig zijn binnen het codeblok van de lus.
- Statement 2: Een conditie: de voorwaarde om de lus te laten draaien, net zoals bij de while en de do ... while-lus.
- Statement 3: Een stukje code dat wordt uitgevoerd telkens de lus door een cyclus is gegaan.
public class Main {
public static void main(String[] args) {
for (int number = 1; number < 6; number++) {
System.out.println("Getal: " + number);
}
}
}
Dit zal als uitvoer het volgende geven:
Getal: 1 Getal: 2 Getal: 3 Getal: 4 Getal: 5
Merk wel op dat als je number declareert binnen de for, dan kun je het niet gebruiken buiten de for-lus.
public class Main {
public static void main(String[] args) {
for (int number = 1; number < 6; number++) {
System.out.println("Getal: " + number);
}
System.out.println("Getal: " + number);
}
}
Doe je het wel dan krijg je de volgende fout:
Main.java:7: error: cannot find symbol System.out.println("Getal: " + number); ^ symbol: variable number location: class Main 1 error
Wil je toch de variabele number toch gebruiken kun je eventueel die declareren buiten de for.
For-each
[bewerken]Een andere manier om een for-lus te gebruiken is met een itereerbaar object (een array of een object dat de interface Iterable implementeert).
for (<statement 1> : <statement 2>) {
// De code die herhaaldelijk moet worden uitgevoerd door de lus.
}
In tegenstelling tot de klassieke for-lus, heeft de for-each twee statements nodig:
- Statement 1: Een declaratie van een geschikte variabele.
- Statement 2: Een referentie naar het te itereren object.
public class Main {
public static void main(String[] args) {
final int[] numberArray = new int[] {4, 6, 8, 10, 12, 20};
for (int number : numberArray) {
System.out.println("Getal: " + number);
}
}
}
Dit zal als uitvoer het volgende geven:
Getal: 4 Getal: 6 Getal: 8 Getal: 10 Getal: 12 Getal: 20
Oneindige lussen
[bewerken]Het grote gevaar bij het gebruik van lussen is dat je door een fout in je code een oneindige lus kunt veroorzaken. Een lus die dus, in theorie, nooit zal stoppen. Neem bijvoorbeeld de while lus die we eerder hadden, als we één kleine fout maken in onze booleaanse expressie kunnen we een oneindige lus veroorzaken.
public class Main {
public static void main(String[] args) {
int number = 1;
while (-number < 6) {
System.out.println("Getal: " + number);
number++;
}
}
}
Hier hebben we in de booleaanse expressie number een negatief getal gemaakt binnen de expressie. Het negatief getal zal altijd kleiner zijn dan nul, dus blijft de lus continue draaien. Om een applicatie moet een oneindige lus te stoppen, kun je bij command line interfaces meestel ctrl+c drukken of bij een IDE is er meestel wel een stop knop.
Break en Continue
[bewerken]Er zijn twee sleutelwoorden die het verloop van een lus kunnen beïnvloeden, namelijk break en continue. Wanneer je in de codeblok van de lus break vermeld zal dit de lus stoppen, continue slaat een iteratie van de lus over.
Onderstaande is een voorbeeld van het gebruik van break:
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
System.out.println("Getal " + i + " voor het gebruik van break");
if (i > 2) {
break;
}
System.out.println("Getal " + i + " na het gebruik van break");
}
}
}
Met als uitvoer:
Getal 1 voor het gebruik van break Getal 1 na het gebruik van break Getal 2 voor het gebruik van break Getal 2 na het gebruik van break Getal 3 voor het gebruik van break
Zoals je ziet wordt de lus gestopt tijdens het getal drie. De code voor de break wordt wel nog uitgevoerd, maar alles erachter en de iteraties van de lus erna niet meer. In volgend voorbeeld wordt break vervangen door continue.
public class Main {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
System.out.println("Getal " + i + " voor het gebruik van break");
if (i > 2) {
continue;
}
System.out.println("Getal " + i + " na het gebruik van break");
}
}
}
Met als uitvoer:
Getal 1 voor het gebruik van break Getal 1 na het gebruik van break Getal 2 voor het gebruik van break Getal 2 na het gebruik van break Getal 3 voor het gebruik van break Getal 4 voor het gebruik van break Getal 5 voor het gebruik van break
Hier kun je zien dat de lus nog steeds verder gaat tot vijf, maar dat het telkens de code na de continue niet meer wordt uitgevoerd zodra i groter is dan twee. Continue stopt of breekt de lus niet maar gaat naar de volgende iteratie zodra Java continue tegenkomt.
Je kunt continue en break bij elk type lus gebruiken. Het is echter niet aangeraden om deze sleutelwoorden te gebruiken, omdat het de leesbaarheid van je code vermindert. Je kunt hetzelfde effect krijgen door aanpassingen te maken aan je conditionele statements of if statements te gebruiken.