Inhoud
- Introductie
- Installatie en Tools
- Je eerste Java‑programma
- Basis Syntax
- Variabelen en Datatypen
- Operators en Expressies
- Controle structuren (if/switch)
- Lussen (for/while)
- Methoden en Parameters
- Arrays en Strings
- Klassen en Objecten
- Overerving en Polymorfisme
- Collecties en Generics
- Foutenafhandeling (Exceptions)
- Best Practices
Hoofdstuk 1 — Introductie
Welkom bij Java Basis voor beginners! In dit hoofdstuk verkennen we wat programmeren in Java inhoudt, hoe een Java‑programma is opgebouwd en hoe je stap voor stap aan de slag gaat. We richten ons op absolute beginners: je hebt geen programmeerervaring nodig. Toch behandelen we meteen praktische voorbeelden zodat je al snel iets werkends ziet.
Doel van dit hoofdstuk:
- Begrijpen wat Java is en waar het voor gebruikt wordt.
- Leren hoe een minimaal Java‑programma eruitziet (structuur van een klasse en de
main‑methode). - De basis van uitvoeren (runnen) en compileren begrijpen.
- Kennismaken met de console (tekstuitvoer) en simpele fouten herkennen.
Wat is Java (kort): Java is een veelgebruikte, moderne programmeertaal die op heel veel systemen kan draaien. Je schrijft broncode in bestanden met de extensie .java. De Java‑compiler (javac) zet deze code om naar bytecode (.class‑bestanden) die door de Java Virtual Machine (JVM) wordt uitgevoerd. Het mooie is dat dezelfde bytecode op verschillende besturingssystemen kan werken (Windows, macOS, Linux). In deze cursus gebruiken we Java 21 (LTS), een recente langetermijnversie.
Waarom Java leren: Java is populair in bedrijfssoftware, Android (via Kotlin/Java interoperabiliteit), gameservers, data‑processing en nog veel meer. De taal heeft uitgebreide bibliotheken, goede tooling en een grote community. Het is ook een mooie opstap naar andere talen omdat veel concepten (variabelen, lussen, functies/methoden) overal terugkomen.
Eerste stappen: Om Java‑code uit te voeren, heb je een JDK (Java Development Kit) nodig. In Hoofdstuk 2 behandelen we installatie en tools. Voor nu volstaat het te weten dat je programma’s met javac compileert en met java start, of via je IDE (bijv. IntelliJ IDEA) direct op de groene Run‑knop klikt.
Belangrijke begrippen die je in dit hoofdstuk alvast ziet:
- Klasse: een sjabloon waaruit objecten gemaakt kunnen worden; hierin schrijf je ook je startpunt (de
main‑methode) voor consoleprogramma’s. - Methode: een herbruikbaar blokje code dat je kunt aanroepen;
mainis zo’n speciale methode. - Statement: een opdracht aan de computer, afgesloten met een puntkomma
;. - Console: het venster waar tekst verschijnt wanneer je
System.out.println(...)gebruikt.
Laten we nu praktisch worden. Hieronder volgen korte, onafhankelijke codevoorbeelden die je direct kunt uitproberen. Kopieer het bestand in een nieuw .java‑bestand met dezelfde klassenaam, compileer en voer uit.
Voorbeeld 1: Het kleinste programma met uitvoer Introductie: Dit is je eerste minimale Java-programma dat één regel tekst naar de console print. Je leert waar de main-methode staat en hoe uitvoer werkt.
public class HalloWereld {
public static void main(String[] args) {
System.out.println("Hallo, wereld!");
}
}
Toelichting: De bestandsnaam moet HalloWereld.java zijn, omdat de klasse HalloWereld heet. De main‑methode is het startpunt.
Voorbeeld 2: Meerdere regels printen Introductie: Dit voorbeeld laat zien hoe je meerdere regels kunt afdrukken en wat een lege regel is.
public class MeerdereRegels {
public static void main(String[] args) {
System.out.println("Eerste regel");
System.out.println("Tweede regel");
System.out.println("Derde regel");
}
}
Tip: Elke aanroep van System.out.println print één regel en voegt een nieuwe regel toe.
Voorbeeld 3: Tekst samenvoegen (concatenatie) Introductie: Je leert strings samenvoegen met het plusteken en variabelen in zinnen gebruiken.
public class Concatenatie {
public static void main(String[] args) {
String voornaam = "Kim";
String achternaam = "Jansen";
System.out.println("Hallo, " + voornaam + " " + achternaam + "!");
}
}
Hier gebruik je het +‑teken om strings samen te voegen.
Voorbeeld 4: Rekenen met gehele getallen Introductie: We oefenen rekenkundige operatoren met gehele getallen en zien wat gehele deling doet.
public class Rekenen {
public static void main(String[] args) {
int a = 12;
int b = 5;
System.out.println("Som: " + (a + b));
System.out.println("Verschil: " + (a - b));
System.out.println("Product: " + (a * b));
System.out.println("Deling (geheel): " + (a / b));
}
}
Let op: a / b met twee integers doet een gehele deling. 12/5 wordt 2, niet 2.4.
Voorbeeld 5: Kommagetallen gebruiken
Introductie: Nu vergelijken we gehele deling met kommagetal-deling door double te gebruiken.
public class Kommagetallen {
public static void main(String[] args) {
double x = 12;
double y = 5;
System.out.println("Deling (double): " + (x / y)); // 2.4
}
}
Wanneer minstens één operand double is, krijg je een kommagetal.
Voorbeeld 6: Commentaar toevoegen Introductie: Commentaar helpt jou en anderen de code te begrijpen; de compiler negeert het.
public class CommentaarDemo {
public static void main(String[] args) {
// Dit is een enkele regel commentaar
/*
Dit is een blokcommentaar over meerdere regels.
Handig voor uitleg of het tijdelijk uitschakelen van code.
*/
System.out.println("Commentaar uitgelegd");
}
}
Commentaar wordt door de compiler genegeerd en helpt je code begrijpelijk houden.
Voorbeeld 7: Unicode en emoji Introductie: Je ziet hoe je Unicode en emoji in console-uitvoer gebruikt en waarom UTF‑8 belangrijk is.
public class UnicodeDemo {
public static void main(String[] args) {
System.out.println("Hallo \u263A"); // Unicode smiley
System.out.println("Hallo 🙂"); // emoji (bronbestand moet UTF-8 zijn)
}
}
Zorg dat je bestand in UTF‑8 gecodeerd is (standaard in moderne IDE’s).
Voorbeeld 8: Foutje maken en begrijpen Introductie: Fouten horen erbij; hier zie je een veelvoorkomende typefout en hoe de compiler je helpt.
public class FoutDemo {
public static void main(String[] args) {
// int a = "tekst"; // Dit geeft een compileerfout: type mismatch
System.out.println("We laten de fout staan als commentaar");
}
}
Elk type heeft regels; een int kan geen tekst bevatten. Je IDE helpt je fouten vroeg te zien.
Voorbeeld 9: Een eenvoudige methode aanroepen Introductie: We maken een eigen methode en roepen die meerdere keren aan om hergebruik te tonen.
public class MethodeDemo {
static void groet(String naam) {
System.out.println("Hallo, " + naam + "!");
}
public static void main(String[] args) {
groet("Saar");
groet("Bo");
}
}
groet is een eigen methode die je hergebruikt. In latere hoofdstukken leer je alles over methoden.
Veelgemaakte beginnersvalkuilen:
- Bestandsnaam en klassenaam komen niet overeen. Oplossing: zorg dat
public class NaaminNaam.javastaat. - Geen
main‑methode. Oplossing: gebruik exactpublic static void main(String[] args). - Vergeten puntkomma
;. Oplossing: elke statement eindigt met;. - Hoofdlettergevoeligheid:
Systemis niet hetzelfde alssystem. - Niet‑UTF‑8 bronbestand waardoor emoji/accents raar tonen. Zet encoding op UTF‑8.
Hoe voer je een programma uit (korte stappen):
- Maak een bestand
HalloWereld.javamet de code uit Voorbeeld 1. - Compileer via terminal:
javac HalloWereld.java. Dit maaktHalloWereld.class. - Voer uit:
java HalloWereld(zonder.class). - Of klik in je IDE op Run bij de
main‑methode.
Koppeling met oefeningen: In de map java-workbook/src/chapter_1 vind je opdrachten die aansluiten op dit hoofdstuk. In java-solutions/src/chapter_1 staan voorbeeldoplossingen. Probeer altijd eerst zelf voordat je naar de uitwerking kijkt!
Samenvatting: Je hebt gezien hoe een simpel Java‑programma is opgebouwd en hoe je uitvoer op de console maakt. Je weet nu wat class, main, statements en strings zijn op hoofdlijnen. In de volgende hoofdstukken gaan we dieper in op tools, syntax en de bouwstenen van de taal.
Hoofdstuk 2 — Installatie en Tools (Java 21)
In dit hoofdstuk leer je stap voor stap hoe je Java 21 installeert, hoe je controleert of alles werkt, en hoe je je eerste programma’s compileert en uitvoert met zowel de terminal als een IDE (IntelliJ IDEA Community). We richten ons volledig op absolute beginners, dus we nemen rustig alle stappen door, inclusief veelvoorkomende problemen en hoe je die oplost.
Wat ga je leren:
- Wat is een JDK en welke versie heb je nodig?
- Java 21 installeren (Temurin/Adoptium of Oracle JDK) en de installatie verifiëren.
- Werken met de terminal:
javaenjavacgebruiken. - IntelliJ IDEA Community installeren en gebruiken (project aanmaken, Run/Debug).
- Basisprojectstructuur en bestandsnamen vs. klassennamen.
- Veelvoorkomende installatieproblemen oplossen.
Over JDK en JVM in één alinea:
De Java Development Kit (JDK) bevat de compiler (javac) en de Java Runtime (JVM). Je schrijft broncode in .java‑bestanden, compileert met javac naar .class‑bestanden (bytecode), en voert die uit met java. De JVM zorgt ervoor dat dezelfde bytecode op meerdere besturingssystemen kan draaien.
Installatiekeuze: Temurin (Adoptium) of Oracle
- Voor beginners is Temurin (Adoptium) vaak de makkelijkste gratis keuze.
- Download Java 21 (LTS) voor jouw besturingssysteem (Windows, macOS, Linux) en volg de installer.
- Op Linux kun je een pakketbeheerder gebruiken (bijv. apt, dnf, pacman); zorg wel dat je specifiek Java 21 pakt.
Na de installatie moet je kunnen controleren of java en javac op je PATH staan en de juiste versie tonen.
Codevoorbeeld 1 — Terminalcontrole van versies (uitvoer is géén code, maar je voert de commando’s uit): Introductie: We controleren of de installatie gelukt is door de versies van java en javac op te vragen.
java -version
javac -version
Verwacht: java version "21" (of openjdk 21) en javac 21.
Waarom twee commando’s? java voert Java‑programma’s uit; javac compileert broncode. Soms staat java wel goed, maar javac niet. Zorg dat beide werken.
Eerste programma compileren en uitvoeren in de terminal Nu je JDK werkt, gaan we een simpel programma maken. Gebruik een teksteditor (of je IDE) en let op de bestandsnaam!
Codevoorbeeld 2 — HalloWereld.java Introductie: Dit is je eerste Java-bronbestand en laat de minimale structuur met main-methode zien.
public class HalloWereld {
public static void main(String[] args) {
System.out.println("Hallo, wereld!");
}
}
Sla dit op als HalloWereld.java (exact dezelfde naam als de klasse). Compileer en voer uit:
Codevoorbeeld 3 — Compilatie en run met javac/java Introductie: Je leert de basisstappen om te compileren met javac en uit te voeren met java.
javac HalloWereld.java
java HalloWereld
Let op: bij java laat je de .class of .java extensie weg; je gebruikt de klassenaam.
Een iets uitgebreider voorbeeld om te zien hoe argumenten werken. Terminalargumenten zijn teksten die je achter de klassenaam zet.
Codevoorbeeld 4 — Programma met argumenten Introductie: We tonen hoe je command-line argumenten leest via de String[] args parameter.
public class ArgumentenDemo {
public static void main(String[] args) {
System.out.println("Aantal argumenten: " + args.length);
if (args.length > 0) {
System.out.println("Eerste argument: " + args[0]);
}
}
}
Compileer en run:
javac ArgumentenDemo.java
java ArgumentenDemo Java21 is leuk
Je ziet hoe args gevuld wordt.
Werken met invoer via de console (Scanner)
Als absolute beginner is het handig om invoer van de gebruiker te lezen. We tonen een veilig en modern voorbeeld met try-with-resources.
Codevoorbeeld 5 — Scanner voor invoer Introductie: Met Scanner kun je gebruikersinvoer lezen; we gebruiken try-with-resources voor veilig sluiten.
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
try (Scanner sc = new Scanner(System.in)) {
System.out.print("Wat is je naam? ");
String naam = sc.nextLine();
System.out.println("Hallo, " + naam + "!");
}
}
}
Je kunt dit ook vanuit de IDE uitvoeren (zie hieronder), of via terminal met java ScannerDemo (na compilatie).
IntelliJ IDEA Community installeren
- Download en installeer IntelliJ IDEA Community (gratis).
- Start de IDE en kies “New Project”. Selecteer Java en controleer dat de SDK op Java 21 staat.
- Maak een nieuw project en voeg een klasse met een
main‑methode toe. - Klik op de groene Run‑knop om het programma te starten.
Projectstructuur en klassenaam Java is streng wat betreft bestandsnaam en klassenaam. De publieksklasse in een bestand moet dezelfde naam hebben als het bestand.
Codevoorbeeld 6 — Verkeerde bestandsnaam (fout illustratie) Introductie: Java koppelt de publieksklasse aan de bestandsnaam; hier zie je wat er misgaat bij een mismatch.
public class DemoNaam {
public static void main(String[] args) {
System.out.println("Dit werkt alleen als het bestand DemoNaam.java heet");
}
}
Sla dit op als DemoNaam.java. Als je het Demo.java noemt, geeft de compiler een foutmelding.
Run‑configuraties in IntelliJ
- Wanneer je op Run klikt boven de
main‑methode, maakt de IDE een Run‑configuratie aan. - Je kunt daar argumenten toevoegen (Program arguments). Probeer dit met
ArgumentenDemo.
Codevoorbeeld 7 — Print vs println (korte demo)
Introductie: Het verschil tussen print (zonder nieuwe regel) en println (met nieuwe regel).
public class PrintDemo {
public static void main(String[] args) {
System.out.print("Zonder nieuwe regel ");
System.out.print("gaat de tekst verder.");
System.out.println();
System.out.println("Met println komt er een nieuwe regel");
}
}
Gebruik print voor aaneengesloten tekst en println voor regels.
Foutmeldingen lezen (compilatiefout vs runtime‑fout)
- Compilatiefouten: gevonden tijdens
javac. Vaak typefouten, ontbrekende puntkomma’s, of verkeerde bestandsnaam. - Runtime‑fouten: treden op tijdens het uitvoeren (bijv. delen door nul, of NumberFormatException bij ongeldige invoer).
Codevoorbeeld 8 — ArithmeticException (delen door nul) Introductie: Een voorbeeld van een runtime-fout en hoe je deze (nog niet) afvangt.
public class DelenDoorNul {
public static void main(String[] args) {
int a = 10;
int b = 0;
// System.out.println(a / b); // zou een runtime-fout geven
System.out.println("Vermijd delen door nul!");
}
}
In latere hoofdstukken leer je hoe je exceptions afhandelt met try/catch.
Gebruik van JavaDoc en hulp in de IDE
- Plaats de cursor op een symbool en gebruik Quick Documentation (meestal F1 of Ctrl+Q) om beschrijvingen te zien.
- De IDE kan kleine problemen markeren met een lampje; klik daarop voor suggesties.
Codevoorbeeld 9 — JavaDoc‑commentaar op een methode Introductie: JavaDoc is gestructureerd commentaar dat documentatie kan genereren en tooling voedt.
public class JavaDocVoorbeeld {
/**
* Geeft de som terug van twee gehele getallen.
* @param a eerste getal
* @param b tweede getal
* @return som van a en b
*/
static int som(int a, int b) {
return a + b;
}
public static void main(String[] args) {
System.out.println(som(2, 3));
}
}
Je ziet hoe commentaar boven een methode extra documentatie biedt.
Omgevingsvariabelen en PATH (korte uitleg voor beginners)
- Op Windows regelt de installer meestal PATH automatisch.
- Op macOS/Linux moet je soms zelf PATH aanpassen in je shellprofiel (
.bashrc,.zshrc). - Controleer altijd
java -versionenjavac -versionin een nieuwe terminal nadat je aanpassingen deed.
Codevoorbeeld 10 — Minimalistische structuur voor meerdere bestanden Introductie: Zo organiseer je meerdere klassen in losse bestanden en laat je één main starten.
// Bestand: App.java
public class App {
public static void main(String[] args) {
Helper.groet("Kim");
}
}
// Bestand: Helper.java
class Helper {
static void groet(String naam) {
System.out.println("Hallo, " + naam);
}
}
Compileer beide bestanden in één keer:
javac App.java Helper.java
java App
Zo zie je dat je meerdere klassen kunt hebben; alleen de klasse met main start je.
Veelvoorkomende installatieproblemen en oplossingen
javawerkt wel,javacniet: je hebt mogelijk alleen de JRE of een onvolledige installatie. Installeer de volledige JDK 21 en controleer PATH.- Meerdere Java‑versies op het systeem: de verkeerde versie staat vooraan op PATH. Pas PATH of je IDE‑SDK aan naar 21.
- IDE vindt de SDK niet: stel in IntelliJ bij Project Structure de juiste SDK (21) in.
- Bestanden met vreemde tekens: zet bestands‑encoding op UTF‑8 (IDE instellingen).
Stap‑voor‑stap checklist voor een werkende setup
- Installeer JDK 21 (Temurin/Adoptium aanbevolen voor beginners).
- Controleer versie met
java -versionenjavac -version. - Installeer IntelliJ IDEA Community en kies SDK 21 bij het aanmaken van een project.
- Maak een klasse met
mainen run via de groene knop. - Probeer in de terminal te compileren en uit te voeren om het verschil te leren.
Koppeling met oefeningen
- In
java-workbook/src/chapter_2.mdvind je praktische opdrachten rond installatie, versies en eenvoudige programma’s, inclusief het werken met de terminal. - In
java-solutions/src/chapter_2.mdvind je richtantwoorden. In volgende hoofdstukken voegen we ook .java‑bestanden met uitwerkingen toe.
Samenvatting
Je hebt geleerd hoe je Java 21 installeert, hoe je controleert of alles werkt, en hoe je met zowel de terminal als een IDE programma’s bouwt en uitvoert. Je kent nu het verschil tussen java en javac, weet hoe je argumenten en invoer gebruikt, en je hebt een idee hoe je fouten herkent. In Hoofdstuk 3 ga je je eerste programma’s uitbreiden en meer oefenen met code schrijven.
Hoofdstuk 3 — Je eerste Java‑programma (van idee tot uitvoer)
In dit hoofdstuk ga je van niets naar een écht werkend programma. Je leert:
- Hoe je een klasse met een
main‑methode schrijft en uitvoert (Java 21). - Hoe je meerdere regels tekst en variabelen print.
- Hoe je eenvoudige berekeningen doet en resultaten toont.
- Hoe je invoer van de gebruiker leest en die verwerkt.
- Hoe je kleine stukjes code (methoden) gebruikt en hergebruikt.
- Hoe je meerdere klassen samen laat werken in een mini‑projectje.
We wisselen uitleg af met korte, direct uitvoerbare voorbeelden. Kopieer elk voorbeeld naar een .java‑bestand met dezelfde klassenaam, compileer met javac en voer uit met java (of gebruik de Run‑knop in je IDE).
Voorbeeld 1 — Het allereerste programma Introductie: Je eerste “Hello, world” laat zien hoe je een klasse met main schrijft en uitvoert.
public class Hello {
public static void main(String[] args) {
System.out.println("Hallo, wereld!");
}
}
Compileren en uitvoeren:
javac Hello.java
java Hello
Je zou in de console Hallo, wereld! moeten zien.
Voorbeeld 2 — Meerdere regels en lege regel Introductie: Demonstratie van meerdere println-aanroepen en een lege regel.
public class RegelsDemo {
public static void main(String[] args) {
System.out.println("Regel 1");
System.out.println(); // lege regel
System.out.println("Regel 3");
}
}
println() zonder tekst print alleen een nieuwe regel.
Voorbeeld 3 — Variabelen en eenvoudige expressies Introductie: Je leert variabelen declareren en eenvoudige rekenexpressies evalueren.
public class VariabelenDemo {
public static void main(String[] args) {
int a = 7;
int b = 5;
System.out.println("a = " + a);
System.out.println("b = " + b);
System.out.println("Som = " + (a + b));
System.out.println("Verschil = " + (a - b));
System.out.println("Product = " + (a * b));
System.out.println("Deling (geheel) = " + (a / b));
}
}
Gehele deling rondt naar beneden; 7/5 is 1.
Voorbeeld 4 — Kommagetallen voor preciezere deling Introductie: Door doubles te gebruiken krijg je een kommagetalresultaat bij deling.
public class DoubleDemo {
public static void main(String[] args) {
double x = 7;
double y = 5;
System.out.println("Deling (double) = " + (x / y)); // 1.4
}
}
Minstens één operand moet double zijn voor een kommagetal.
Voorbeeld 5 — String‑concatenatie en escape‑tekens Introductie: We voegen tekst samen en gebruiken escape‑tekens voor speciale symbolen.
public class TekstDemo {
public static void main(String[] args) {
String naam = "Kim";
System.out.println("Hallo, \"" + naam + "\"!"); // aanhalingstekens escapen
System.out.println("Pad: C:\\Users\\Kim"); // backslash escapen
System.out.println("Nieuwe\nregel"); // \n = newline
}
}
Escape‑tekens beginnen met \.
Voorbeeld 6 — Lees invoer met Scanner Introductie: Met Scanner lees je tekst van de gebruiker en verwerk je die in je programma.
import java.util.Scanner;
public class InvoerDemo {
public static void main(String[] args) {
try (Scanner sc = new Scanner(System.in)) {
System.out.print("Wat is je naam? ");
String naam = sc.nextLine();
System.out.print("Hoe oud ben je? ");
int leeftijd = Integer.parseInt(sc.nextLine());
System.out.println("Hallo, " + naam + ", je bent " + leeftijd + " jaar.");
}
}
}
Tip: we gebruiken nextLine() en parsen expliciet naar int om beginnersfouten met nextInt() te voorkomen.
Voorbeeld 7 — Een eigen methode maken en aanroepen Introductie: We isoleren herhaalde logica in een methode en roepen die opnieuw aan.
public class MethodeDemo {
static void groet(String naam) {
System.out.println("Hoi " + naam + "!");
}
public static void main(String[] args) {
groet("Saar");
groet("Bo");
}
}
Met methoden kun je herhaling verminderen en je code logischer indelen.
Voorbeeld 8 — Beslisstructuur (if/else) op basis van invoer Introductie: Met een if/else neem je een beslissing op basis van invoer van de gebruiker.
import java.util.Scanner;
public class IfElseDemo {
public static void main(String[] args) {
try (Scanner sc = new Scanner(System.in)) {
System.out.print("Voer een getal in: ");
int n = Integer.parseInt(sc.nextLine());
if (n % 2 == 0) {
System.out.println(n + " is even");
} else {
System.out.println(n + " is oneven");
}
}
}
}
Hier zie je een eenvoudige beslissing op basis van een voorwaarde.
Voorbeeld 9 — Een eenvoudige lus (for) om herhaling te automatiseren Introductie: De for-lus herhaalt code een vast aantal keren en gebruikt een teller.
public class ForDemo {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
System.out.println("i = " + i);
}
}
}
Lussen behandelen we dieper in een later hoofdstuk, maar hier zie je alvast de vorm.
Voorbeeld 10 — Meerdere klassen laten samenwerken Introductie: Je ziet hoe twee hulpkklassen samenwerken met een hoofdklasse die de applicatie start.
public class App {
public static void main(String[] args) {
Helper.groet("Kim");
int uitkomst = Rekenaar.som(3, 4);
System.out.println("Som = " + uitkomst);
}
}
class Helper {
static void groet(String naam) {
System.out.println("Hallo, " + naam);
}
}
class Rekenaar {
static int som(int a, int b) {
return a + b;
}
}
Je mag meerdere klassen in één bestand zetten zolang er maximaal één public klasse is en de bestandsnaam overeenkomt met die klasse (hier App).
Veelgemaakte beginnersfouten en tips
- Verkeerde bestandsnaam:
public class Hellomoet inHello.javastaan. - Geen
main‑methode: zorg voor exactpublic static void main(String[] args). - Vergeten puntkomma; IDE waarschuwt je met een rode golf.
- Onjuiste encoding: stel je project in op UTF‑8, anders kunnen emoji/accents raar tonen.
- Console blijft niet open bij dubbelklikken in sommige omgevingen: voer programma’s uit via terminal of IDE, niet door op
.classte dubbelklikken.
Mini‑stapjes naar je eigen app
- Maak
Hello.javaen run het. - Voeg variabelen toe en print een rekensom.
- Lees invoer met
Scanneren verwerk die in een zin. - Stop herhaalde code in een eigen methode.
- Splits functionaliteit over meerdere klassen.
Koppeling met oefeningen
- Ga naar
java-workbook/src/chapter_3.mdvoor oefeningen die aansluiten op dit hoofdstuk (eigen methode, print vs println, enz.). - Check
java-solutions/src/chapter_3.mdvoor voorbeeldantwoorden (kijk pas na het proberen!).
Samenvatting Je hebt nu een ‘van nul naar iets’ pad gevolgd: printen, rekenen, invoer lezen, methoden gebruiken en meerdere klassen laten samenwerken. Dit vormt de basis voor alle volgende hoofdstukken. In Hoofdstuk 4 duiken we dieper in de basissyntax en regels waar Java zich aan houdt.
Hoofdstuk 4 — Basis Syntax (regels, vormen en voorbeelden)
In dit hoofdstuk leer je de schrijfregels van Java: hoe je geldige uitspraken (statements) maakt, hoe blokken met {} werken, waar je puntkomma’s plaatst, hoe je namen (identifiers) kiest, en welke trefwoorden (keywords) gereserveerd zijn. Omdat we ons richten op absolute beginners, laten we elk concept zien met duidelijke, kleine voorbeelden. Aan het eind herken je typische syntaxfouten direct en kun je ze snel herstellen.
Kernideeën die je gaat zien:
- Java is hoofdlettergevoelig:
Systemis iets anders dansystem. - Elke statement eindigt met
;(behalve blok- en structurele regels zoalsif (...) { ... }). - Blokken code staan tussen
{en}en bepalen de “scope” (zichtbaarheid) van variabelen. - Namen van klassen beginnen normaal gesproken met een hoofdletter (PascalCase), methoden/variabelen met een kleine letter (camelCase).
- Spaties en nieuwe regels maken de code leesbaar, maar ze veranderen (bijna) nooit de betekenis.
- Java kent gereserveerde woorden (zoals
class,if,for,switch) die je niet als variabelenaam mag gebruiken.
Laten we stap voor stap de belangrijkste stukken syntax bekijken.
Voorbeeld 1 — De vorm van een klasse en de main‑methode
Introductie: We bekijken de basisvorm van een Java‑klasse en waar de main‑methode staat.
public class VormDemo {
public static void main(String[] args) {
System.out.println("Hallo uit VormDemo");
}
}
Regels: de bestandsnaam moet VormDemo.java zijn, puntkomma’s aan het einde van statements, en de main‑methode heeft exact de signatuur public static void main(String[] args).
Voorbeeld 2 — Witte ruimte: spaties en nieuwe regels Introductie: Extra spaties en nieuwe regels beïnvloeden de betekenis nauwelijks; ze helpen vooral leesbaarheid.
public class Witruimte {
public static void main(String[] args) {
System.out.println("Dit" + " werkt");
System.out.println("Ook dit werkt");
System.out.println(
"En zelfs met nieuwe regels tussen argumenten"
);
}
}
Spaties en nieuwe regels zijn meestal voor menselijk leesgemak; de compiler negeert extra witruimte.
Voorbeeld 3 — Puntkomma’s en blokken
Introductie: Statements eindigen met ; en blokken {} bepalen scope en levensduur van variabelen.
public class PuntkommaEnBlokken {
public static void main(String[] args) {
int a = 3; int b = 4; // twee statements op één regel (kan, maar minder leesbaar)
{
int c = a + b; // c is alleen binnen dit blok zichtbaar
System.out.println("c = " + c);
}
// System.out.println(c); // compileerfout: c bestaat hier niet meer
}
}
Een statement eindigt op ;. Een blok { ... } kan variabelen afschermen voor de buitenwereld.
Voorbeeld 4 — Namen (identifiers) en conventies Introductie: Goede naamgeving maakt code leesbaar; let op conventies voor klassen en variabelen.
public class NaamConventies {
static int MAXIMUM_AANTAL = 10; // constante: vaak UPPER_SNAKE_CASE
static int minimumAantal = 1; // variabele/methode: camelCase
public static void main(String[] args) {
int aantalStudenten = 3;
System.out.println("aantalStudenten = " + aantalStudenten);
}
}
Je mag letters, cijfers, _ en $ gebruiken, maar geen spatie of met een cijfer beginnen. Gebruik betekenisvolle namen.
Voorbeeld 5 — Keywords (gereserveerde woorden)
public class KeywordsDemo {
public static void main(String[] args) {
// int class = 5; // mag niet: "class" is gereserveerd
int klasse = 5; // dit mag wel (maar gebruik liever echte betekenisvolle namen)
System.out.println(klasse);
}
}
Bekende keywords: class, if, else, for, while, switch, case, break, continue, return, try, catch, finally, new, public, private, protected, static, void, enz.
Voorbeeld 6 — Expressies en operatoren
public class ExpressiesDemo {
public static void main(String[] args) {
int a = 5 + 2 * 3; // vermenigvuldiging eerst (prioriteit)
int b = (5 + 2) * 3; // haakjes veranderen de volgorde
boolean groot = a > b; // vergelijking levert boolean op
System.out.println("a = " + a + ", b = " + b + ", groot = " + groot);
}
}
Je combineert waarden en operatoren tot expressies die een resultaat opleveren.
Voorbeeld 7 — If/else‑blokken en scopes
public class IfElseBlokken {
public static void main(String[] args) {
int score = 55;
if (score >= 60) {
String bericht = "Geslaagd";
System.out.println(bericht);
} else {
String bericht = "Gezakt"; // ander bericht in een ander blok
System.out.println(bericht);
}
// buiten de blokken bestaan deze lokale variabelen niet meer
}
}
Variabelen die in een blok gedeclareerd zijn, leven niet buiten dat blok.
Voorbeeld 8 — Switch‑expressie (Java 21) en pijl‑syntaxis
public class SwitchPijlen {
public static void main(String[] args) {
int dag = 3;
String naam = switch (dag) {
case 1 -> "Maandag";
case 2 -> "Dinsdag";
case 3 -> "Woensdag";
case 4 -> "Donderdag";
case 5 -> "Vrijdag";
case 6, 7 -> "Weekend";
default -> "Onbekend";
};
System.out.println(naam);
}
}
In moderne Java kun je switch als expressie gebruiken die direct een waarde oplevert.
Voorbeeld 9 — For/while/do‑while vormen
public class LussenVormen {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
System.out.println("for: " + i);
}
int j = 0;
while (j < 3) {
System.out.println("while: " + j);
j++;
}
int k = 0;
do {
System.out.println("do-while: " + k);
k++;
} while (k < 3);
}
}
De vorm (plaats van initialisatie/voorwaarden) bepaalt hoe de lus verloopt.
Voorbeeld 10 — Methoden: definitie en aanroep
public class MethodenVorm {
static int som(int a, int b) {
return a + b; // return beëindigt de methode en levert een waarde
}
public static void main(String[] args) {
int uitkomst = som(2, 3);
System.out.println("som = " + uitkomst);
}
}
Methodesignature: naam, parameterlijst met types, en het returntype. void betekent: geen waarde terug.
Voorbeeld 11 — String‑literal, char‑literal en escaping
public class TekstLiterals {
public static void main(String[] args) {
String s = "Hallo\nwereld"; // \n is newline
char c = '\''; // enkel aanhalingsteken als char
System.out.println(s);
System.out.println("char: " + c);
}
}
Let op het verschil tussen "..." voor String en '...' voor een char.
Voorbeeld 12 — Commentaar en JavaDoc
public class CommentaarVorm {
/**
* Tel twee getallen bij elkaar op.
*/
static int telOp(int a, int b) {
return a + b; // inline opmerking
}
public static void main(String[] args) {
// Een enkele regel commentaar
System.out.println(telOp(1, 2));
/*
Blokcommentaar voor langere toelichting.
*/
}
}
Gebruik commentaar spaarzaam om intentie te verduidelijken.
Veelgemaakte syntaxfouten en hoe je ze oplost
- Vergeten
;aan het einde van een statement → voeg de puntkomma toe waar de IDE de fout markeert. - Accolades niet in balans (
{zonder}) → laat de IDE automatisch herschikken of voeg de ontbrekende bracket toe. - Naam/bestand klopt niet met
public class→ hernoem het bestand of de klasse zodat ze overeenkomen. - Hoofdletterfout (
systemi.p.v.System) → Java is case‑sensitive; corrigeer de hoofdletters. - Keyword als variabelenaam → kies een andere, geldige naam.
Stijlrichtlijnen die je nu al kunt volgen
- Consistente inspringing (2 of 4 spaties; kies één en blijf daarbij).
- Spaties rond operatoren:
a + bleest prettiger dana+b. - Maximaal één publieksklasse per
.java‑bestand en die moet de bestandsnaam bepalen.
Koppeling met oefeningen
- Zie
java-workbook/src/chapter_4.mdvoor opdrachten over blokken, statements, switch‑expressie en lussen. - Zie
java-solutions/src/chapter_4.mdvoor voorbeeldoplossingen.
Samenvatting
Je hebt de basisvormen van Java‑syntax gezien: statements met puntkomma’s, blokken met {} en scopes, namen en conventies, operators en controlestromen, methoden, en string/char‑literals. Met deze “taalregels” kun je alle komende hoofdstukken beter begrijpen en fouten sneller oplossen.
Hoofdstuk 5 — Variabelen en Datatypen (bouwstenen van gegevens)
In dit hoofdstuk leer je welke soorten gegevens (datatypen) Java kent en hoe je er veilig mee werkt. We starten met primitieve typen (zoals int en double) en verkennen vervolgens referentietypen (zoals String en zelfgemaakte klassen). Je leert ook over typeconversie (casting), initialisatie, standaardwaarden, immutability van strings, en veelgemaakte valkuilen.
Wat ga je leren:
- Verschil tussen primitieve en referentietypen.
- Overzicht van primitieve typen: boolean, byte, short, int, long, float, double, char.
- Literalen (bijv. 123, 12.34, 'A', "tekst") inclusief underscores in numerieke literalen.
- Typeconversie: impliciet en expliciet (casting), en wat er gebeurt bij overloop (overflow).
- Werken met String (immutable), StringBuilder (mutable) en basishandelingen.
- Var (type-inferentie) sinds Java 10: wanneer wel en wanneer niet gebruiken.
Voorbeeld 1 — Primitieven declareren en initialiseren
public class PrimitievenDemo {
public static void main(String[] args) {
int leeftijd = 20;
double prijs = 19.99;
boolean actief = true;
char initiaal = 'J';
long populatie = 8_100_000_000L; // L suffix voor long
float temperatuur = 21.5f; // f suffix voor float
System.out.println(leeftijd + ", " + prijs + ", " + actief + ", " + initiaal + ", " + populatie + ", " + temperatuur);
}
}
Voorbeeld 2 — Standaardwaarden in velden (niet in lokale variabelen)
public class Standaardwaarden {
static int standaardInt; // 0
static boolean standaardBool; // false
static double standaardDouble;// 0.0
static String standaardRef; // null
public static void main(String[] args) {
int lokaal; // lokale variabelen MOET je initialiseren
// System.out.println(lokaal); // compileerfout
System.out.println(standaardInt + ", " + standaardBool + ", " + standaardDouble + ", " + standaardRef);
}
}
Voorbeeld 3 — Casting en overflow
public class CastingOverflow {
public static void main(String[] args) {
int a = 130;
byte b = (byte) a; // past niet in byte (-128..127) → overflow
System.out.println("a = " + a + ", b = " + b); // b kan -126 zijn
double x = 3.9;
int y = (int) x; // truncatie naar 3
System.out.println("y = " + y);
}
}
Voorbeeld 4 — Impliciete promotie bij rekenen
public class PromotieDemo {
public static void main(String[] args) {
byte b1 = 10, b2 = 20;
int som = b1 + b2; // promotie naar int bij optelling
long l = 1_000_000_000L;
long product = l * 2; // let op type: int*int kan overflow geven
System.out.println("som = " + som + ", product = " + product);
}
}
Voorbeeld 5 — Strings zijn immutable
public class StringImmutability {
public static void main(String[] args) {
String s = "Java";
String t = s.toUpperCase(); // maakt een nieuw String-object
System.out.println(s); // "Java"
System.out.println(t); // "JAVA"
}
}
Voorbeeld 6 — StringBuilder voor efficiënte opbouw
public class StringBuilderDemo {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("Hallo").append(", ").append("wereld!");
System.out.println(sb.toString());
}
}
Voorbeeld 7 — Literalen en underscores
public class LiteralenDemo {
public static void main(String[] args) {
int miljoen = 1_000_000; // underscores voor leesbaarheid
double pi = 3.141_592_653_589;
char euro = '\u20AC'; // Unicode literal
System.out.println(miljoen + ", " + pi + ", " + euro);
}
}
Voorbeeld 8 — var (type-inferentie) verstandig gebruiken
public class VarDemo {
public static void main(String[] args) {
var a = 10; // a is int
var b = 10.0; // b is double
var tekst = "Hallo"; // tekst is String
// var x; // mag niet: moet direct worden geïnitialiseerd
System.out.println(a + ", " + b + ", " + tekst);
}
}
Voorbeeld 9 — Wrapper-klassen en autoboxing
public class WrappersDemo {
public static void main(String[] args) {
Integer i = 10; // autoboxing van int naar Integer
int j = i; // unboxing
Boolean flag = Boolean.TRUE;
System.out.println(i + j + (flag ? 1 : 0));
}
}
Veelgemaakte fouten en tips:
- Vergeet suffixen niet: gebruik
Lvoor long-literal enfvoor float. - Vermijd onnodige casts; ze kunnen informatie verliezen (truncatie/overflow).
- Wees bewust dat String immutable is; gebruik StringBuilder bij veel concatenaties in lussen.
- Lokale variabelen moeten vóór gebruik geïnitialiseerd worden.
Koppeling met oefeningen:
- Zie
java-workbook/src/chapter_5.mdvoor opdrachten over types, casting en strings. - Uitwerkingen in
java-solutions/src/chapter_5.mden bijbehorende Java-bestanden.
Hoofdstuk 6 — Operators en Expressies (rekenen en logica in Java)
In dit hoofdstuk duiken we in operatoren: symbolen waarmee je rekent, vergelijkt en logische beslissingen maakt. Je ziet ook toekenningsoperatoren, samengestelde toekenning (+=, -=), incrementeer/decrementeer (++, --), en de volgorde van evaluatie en prioriteiten.
Categorieën operatoren die je leert:
- Reken:
+ - * / % - Vergelijking:
== != < > <= >= - Logisch:
&& || !(kortsluitend AND/OR) - Toekenning:
=, samengestelde:+=,-=,*=,/=,%= - Incrementeer/decrementeer:
++,--(prefix en postfix) - Bitwise (kort):
& | ^ ~ << >> >>>(voor gevorderden, hier kort aangestipt) - Ternary:
voorwaarde ? waarde1 : waarde2
Voorbeeld 1 — Basisrekenen Introductie: We oefenen de rekenoperatoren en laten zien wat elke bewerking oplevert.
public class RekenDemo {
public static void main(String[] args) {
int a = 5, b = 2;
System.out.println("som = " + (a + b));
System.out.println("verschil = " + (a - b));
System.out.println("product = " + (a * b));
System.out.println("deling (geheel) = " + (a / b));
System.out.println("modulo (rest) = " + (a % b));
}
}
Toelichting: Let op het verschil tussen gehele deling en modulo; modulo geeft de restwaarde van een deling.
Voorbeeld 2 — Deling met double Introductie: We laten zien dat deling met doubles een kommagetal oplevert.
public class DoubleDeling {
public static void main(String[] args) {
double x = 5, y = 2;
System.out.println(x / y); // 2.5
}
}
Toelichting: Door doubles te gebruiken krijg je 2.5 in plaats van een gehele uitkomst.
Voorbeeld 3 — Vergelijkingen en boolean Introductie: We vergelijken waarden en laten zien dat het resultaat een boolean is.
public class VergelijkDemo {
public static void main(String[] args) {
int a = 5, b = 2;
System.out.println(a > b); // true
System.out.println(a == b); // false
System.out.println(a != b); // true
}
}
Toelichting: Vergelijkingsoperatoren leveren true/false; gebruik ze in beslissingen.
Voorbeeld 4 — Logische operatoren met kortsluiting Introductie: We demonstreren kortsluiting: de rechter operand wordt soms niet geëvalueerd.
public class LogischDemo {
static boolean test(String naam, boolean resultaat) {
System.out.println("test(" + naam + ")");
return resultaat;
}
public static void main(String[] args) {
boolean z = test("A", false) && test("B", true); // B wordt niet meer aangeroepen
boolean w = test("C", true) || test("D", false); // D wordt niet meer aangeroepen
System.out.println(z);
System.out.println(w);
}
}
Toelichting: Bij && stopt evaluatie zodra links al false is; bij || zodra links true is.
Voorbeeld 5 — Samengestelde toekenning en ++/-- Introductie: We tonen het effect van samengestelde toekenning en het verschil tussen prefix en postfix.
public class ToekenningDemo {
public static void main(String[] args) {
int x = 10;
x += 5; // 15
x *= 2; // 30
int y = 3;
System.out.println(++y); // prefix: verhoog, dan gebruik (4)
System.out.println(y++); // postfix: gebruik, dan verhoog (4)
System.out.println(y); // nu 5
}
}
Toelichting: ++y verhoogt vóór gebruik; y++ verhoogt na gebruik. Samengestelde toekenning past de waarde direct aan.
Voorbeeld 6 — Prioriteit en haakjes Introductie: Operatorprioriteit bepaalt volgorde; haakjes maken de intentie expliciet.
public class PrioriteitDemo {
public static void main(String[] args) {
int uitkomst = 2 + 3 * 4; // 14
int metHaakjes = (2 + 3) * 4; // 20
System.out.println(uitkomst + ", " + metHaakjes);
}
}
Toelichting: Zonder haakjes kan de uitkomst verrassen; zet haakjes voor duidelijkheid.
Voorbeeld 7 — Ternary operator Introductie: De voorwaardelijke operator kiest tussen twee waarden op basis van een conditie.
public class TernaryDemo {
public static void main(String[] args) {
int score = 62;
String resultaat = score >= 60 ? "Geslaagd" : "Gezakt";
System.out.println(resultaat);
}
}
Toelichting: Handig voor compacte toekenningen of inline keuzes (bijv. in prints).
Voorbeeld 8 — Valstrikken met == en Strings
Introductie: == vergelijkt referenties; voor inhoudsvergelijking gebruik je equals.
public class StringVergelijking {
public static void main(String[] args) {
String a = "Java";
String b = new String("Java");
System.out.println(a == b); // false: vergelijkt referenties
System.out.println(a.equals(b)); // true: vergelijkt inhoud
}
}
Toelichting: Gebruik equals voor String-inhoud; == kan onverwacht false geven bij verschillende objecten.
Voorbeeld 9 — Bitwise (korte demo) Introductie: We tonen basis bitbewerkingen en verschuivingen op binaire waarden.
public class BitwiseDemo {
public static void main(String[] args) {
int m = 0b0011; // 3
int n = 0b0101; // 5
System.out.println(m & n); // 1
System.out.println(m | n); // 7
System.out.println(m ^ n); // 6
System.out.println(n << 1); // 10
}
}
Toelichting: &, |, ^ werken op bits; << verschuift links (maal 2), >> arithmetic shift, >>> logical shift.
Veelgemaakte fouten en tips:
- Gebruik haakjes om de intentie duidelijk te maken, zeker bij gemengde operatoren.
- Onthoud:
&&en||zijn kortsluitend (rechts wordt niet geëvalueerd als links al voldoende is). - Vergelijk Strings met
equals, niet met==.
Koppeling met oefeningen:
- Zie
java-workbook/src/chapter_6.mdvoor opdrachten over operatoren en expressies. - Uitwerkingen in
java-solutions/src/chapter_6.md.
Hoofdstuk 7 — Controlestructuren (if, else, switch) voor beslissingen
Beslissingen vormen de kern van logica in je programma. Met if/else toets je voorwaarden; met switch kies je uit meerdere takken. In moderne Java (21) kun je switch ook als expressie gebruiken die een waarde oplevert.
Voorbeeld 1 — Basis if/else Introductie: Eenvoudige keuze tussen twee paden op basis van een voorwaarde.
public class IfElseBasis {
public static void main(String[] args) {
int score = 75;
if (score >= 60) {
System.out.println("Geslaagd");
} else {
System.out.println("Gezakt");
}
}
}
Toelichting: Gebruik if/else wanneer er twee mogelijke uitkomsten zijn.
Voorbeeld 2 — Meerdere if/else-if takken Introductie: Kies uit meer dan twee categorieën met else-if ketens.
public class CijferBeoordeling {
public static void main(String[] args) {
int score = 83;
if (score >= 90) {
System.out.println("Uitmuntend");
} else if (score >= 75) {
System.out.println("Goed");
} else if (score >= 60) {
System.out.println("Voldoende");
} else {
System.out.println("Onvoldoende");
}
}
}
Toelichting: Houd de voorwaarden eenvoudig; bij lange ketens kan een switch of mapping duidelijker zijn.
Voorbeeld 3 — Ingesloten if (nested) en leesbaarheid Introductie: Geneste if’s kunnen logica uitdrukken, maar kunnen snel onleesbaar worden.
public class NestedIf {
public static void main(String[] args) {
int leeftijd = 20;
boolean lid = true;
if (leeftijd >= 18) {
if (lid) {
System.out.println("Volwassen lid");
} else {
System.out.println("Volwassen geen lid");
}
} else {
System.out.println("Minderjarig");
}
}
}
Toelichting: Overweeg vroege returns of hulpmethoden om diepe nesting te vermijden.
Voorbeeld 4 — Switch (statement) met pijl-syntaxis Introductie: Gebruik switch voor vaste, op één variabele gebaseerde keuzes.
public class SwitchStatementDemo {
public static void main(String[] args) {
int dag = 3;
switch (dag) {
case 1 -> System.out.println("Maandag");
case 2 -> System.out.println("Dinsdag");
case 3 -> System.out.println("Woensdag");
case 4 -> System.out.println("Donderdag");
case 5 -> System.out.println("Vrijdag");
case 6, 7 -> System.out.println("Weekend");
default -> System.out.println("Onbekend");
}
}
}
Toelichting: De pijl-syntaxis is kort en voorkomt fall‑through.
Voorbeeld 5 — Switch als expressie met returnwaarde Introductie: Switch kan ook een waarde opleveren die je direct kunt toewijzen.
public class SwitchExpressieDemo {
public static void main(String[] args) {
int maand = 2;
int dagen = switch (maand) {
case 1, 3, 5, 7, 8, 10, 12 -> 31;
case 4, 6, 9, 11 -> 30;
case 2 -> 28; // schrikkeljaren laten we hier buiten beschouwing
default -> throw new IllegalArgumentException("Onbekende maand: " + maand);
};
System.out.println("Dagen: " + dagen);
}
}
Toelichting: De default-tak is verplicht voor volledigheid; of gooi een betekenisvolle exception.
Voorbeeld 6 — yield in switch-blokken
Introductie: Gebruik yield om vanuit een blok een waarde terug te geven.
public class SwitchYieldDemo {
public static void main(String[] args) {
String rol = "admin";
int niveau = switch (rol) {
case "gast" -> 0;
case "gebruiker" -> 1;
case "admin" -> {
System.out.println("Extra checks...");
yield 2; // geef waarde terug vanuit blok
}
default -> -1;
};
System.out.println(niveau);
}
}
Toelichting: Binnen blokken kun je extra statements uitvoeren voordat je een waarde ‘yields’.
Voorbeeld 7 — Valstrik: toekennings- vs vergelijkingsoperator
Introductie: Een veelgemaakte fout is = (toekennen) gebruiken i.p.v. == (vergelijken).
public class AssignVsEquals {
public static void main(String[] args) {
boolean vlag = false;
// if (vlag = true) { ... } // fout: dit is toekenning
if (vlag == true) {
System.out.println("waar");
} else {
System.out.println("niet waar");
}
}
}
Toelichting: De compiler zou deze fout soms niet waarschuwen zonder @SuppressWarnings; voorkom het door == te gebruiken.
Voorbeeld 8 — Guard clauses (vroeg terugkeren) Introductie: Met guard clauses keer je vroeg terug en hou je methoden plat en leesbaar.
public class GuardClauses {
static String beschrijf(int n) {
if (n < 0) return "negatief";
if (n == 0) return "nul";
return "positief";
}
public static void main(String[] args) {
System.out.println(beschrijf(-5));
System.out.println(beschrijf(0));
System.out.println(beschrijf(7));
}
}
Toelichting: Minder nesting en duidelijke ‘speciale gevallen’ verbeteren de leesbaarheid.
Voorbeeld 9 — Combineren met logische operatoren Introductie: Combineer voorwaarden met EN (&&) en OF (||) voor expressieve checks.
public class Combinaties {
public static void main(String[] args) {
int leeftijd = 19;
boolean toestemmingOuder = true;
if (leeftijd >= 18 || toestemmingOuder) {
System.out.println("toestaan");
}
if (leeftijd >= 18 && toestemmingOuder) {
System.out.println("speciaal tarief");
}
}
}
Toelichting: Gebruik || voor alternatieve toegang en && voor samenlopende eisen.
Tips:
- Gebruik
switchwanneer je op één variabele meerdere vaste gevallen afhandelt. - Gebruik
if/elsebij complexe of samengestelde voorwaarden. - Schrijf compacte, leesbare voorwaarden; overweeg hulp-methoden voor duidelijkheid.
Koppeling met oefeningen:
- Zie
java-workbook/src/chapter_7.mdvoor opdrachten met if/else en switch-expressies. - Uitwerkingen in
java-solutions/src/chapter_7.md.
Hoofdstuk 8 — Lussen (for, while, do-while, foreach)
Herhaling automatiseer je met lussen. Je leert de vormen for, while, do-while en de enhanced for (foreach) voor arrays en collecties.
Voorbeeld 1 — Klassieke for-lus Introductie: De klassieke for-lus gebruikt een teller met start, voorwaarde en update.
public class ForKlassiek {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
System.out.println(i);
}
}
}
Toelichting: Gebruik een for-lus als je precies weet hoe vaak je herhaalt.
Voorbeeld 2 — While-lus Introductie: While herhaalt zolang de voorwaarde waar is; controle vindt plaats vóór de iteratie.
public class WhileDemo {
public static void main(String[] args) {
int j = 0;
while (j < 3) {
System.out.println(j);
j++;
}
}
}
Toelichting: While is handig als het aantal herhalingen niet vaststaat en verandert op basis van runtime-waarden.
Voorbeeld 3 — Do-while (voert het blok minimaal één keer uit)
public class DoWhileDemo {
public static void main(String[] args) {
int k = 0;
do {
System.out.println(k);
k++;
} while (k < 3);
}
}
Voorbeeld 4 — Enhanced for (foreach) met array
public class ForEachArray {
public static void main(String[] args) {
int[] cijfers = {7, 8, 9};
for (int c : cijfers) {
System.out.println(c);
}
}
}
Voorbeeld 5 — break en continue
public class BreakContinueDemo {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
if (i == 2) continue; // sla 2 over
if (i == 4) break; // stop bij 4
System.out.println(i);
}
}
}
Voorbeeld 6 — Geneste lussen en complexiteit
public class GenesteLussen {
public static void main(String[] args) {
for (int r = 1; r <= 3; r++) {
for (int c = 1; c <= 3; c++) {
System.out.print(r + "," + c + " ");
}
System.out.println();
}
}
}
Voorbeeld 7 — Oneindige lus met exit-voorwaarde
public class OneindigMetExit {
public static void main(String[] args) {
int i = 0;
while (true) {
if (i == 3) break;
System.out.println(i);
i++;
}
}
}
Voorbeeld 8 — Valstrik: wijzig niet de iterator in foreach
public class ForEachValstrik {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
for (int v : arr) {
// v++ wijzigt NIET het arrayelement; v is een kopie
System.out.println(v);
}
}
}
Tips:
- Kies de lus die je intentie het best uitdrukt: foreach voor iteratie zonder index.
- Vermijd oneindige lussen tenzij je expliciet een stopconditie hebt.
- Werk aan leesbaarheid: vermijd te diepe geneste lussen; splits op in methoden.
Koppeling met oefeningen:
- Zie
java-workbook/src/chapter_8.mdvoor loop-oefeningen. - Uitwerkingen in
java-solutions/src/chapter_8.md.
Hoofdstuk 9 — Methoden en Parameteroverdracht (structuur en hergebruik)
Methoden groeperen gedrag en maken code herbruikbaar. Je leert methodesignatures, parameters, returntypes, overloading, parameter-passing (by value), en scope van variabelen. Ook kijken we kort naar statische vs. instantie-methoden.
Voorbeeld 1 — Basis: definitie en aanroep
public class MethodenBasis {
static int som(int a, int b) {
return a + b;
}
public static void main(String[] args) {
System.out.println(som(2, 3));
}
}
Voorbeeld 2 — Return typen en void
public class ReturnVoid {
static double gemiddelde(int a, int b) {
return (a + b) / 2.0;
}
static void groet(String naam) {
System.out.println("Hallo, " + naam);
}
public static void main(String[] args) {
System.out.println(gemiddelde(3, 5));
groet("Kim");
}
}
Voorbeeld 3 — Overloading (zelfde naam, andere parameters)
public class OverloadingDemo {
static int som(int a, int b) { return a + b; }
static double som(double a, double b) { return a + b; }
public static void main(String[] args) {
System.out.println(som(2, 3));
System.out.println(som(2.5, 3.1));
}
}
Voorbeeld 4 — Parameteroverdracht: by value
public class PassByValue {
static void verhoog(int x) {
x++; // werkt op kopie
}
public static void main(String[] args) {
int a = 10;
verhoog(a);
System.out.println(a); // nog steeds 10
}
}
Voorbeeld 5 — Referenties doorgeven (objecten)
class Doos { int waarde; }
public class PassByValueRef {
static void setTien(Doos d) {
d.waarde = 10; // de referentie is by value, maar wijzigt het object
}
public static void main(String[] args) {
Doos d = new Doos();
d.waarde = 5;
setTien(d);
System.out.println(d.waarde); // 10
}
}
Voorbeeld 6 — Scope en schaduw (shadowing)
public class ScopeDemo {
static int x = 1; // klasseveld
public static void main(String[] args) {
int x = 2; // lokale variabele overschaduwt veld
System.out.println(x); // 2
System.out.println(ScopeDemo.x); // 1
}
}
Voorbeeld 7 — Statisch vs instantie-methoden
class Rekenaar {
int basis; // instantieveld
Rekenaar(int basis) { this.basis = basis; }
int telBij(int a) { return basis + a; } // instantie
static int som(int a, int b) { return a + b; } // statisch
}
public class StatischInstantie {
public static void main(String[] args) {
System.out.println(Rekenaar.som(3, 4)); // statisch
Rekenaar r = new Rekenaar(10);
System.out.println(r.telBij(5)); // instantie
}
}
Voorbeeld 8 — Varargs (variabel aantal parameters)
public class VarargsDemo {
static int som(int... getallen) {
int totaal = 0;
for (int g : getallen) totaal += g;
return totaal;
}
public static void main(String[] args) {
System.out.println(som(1));
System.out.println(som(1, 2, 3));
System.out.println(som());
}
}
Voorbeeld 9 — Documenteer met JavaDoc
public class JavaDocDemo {
/**
* Berekent de maximale waarde in een array.
* @param data array van ints (niet null, lengte > 0)
* @return de grootste int in data
*/
static int max(int[] data) {
int m = data[0];
for (int v : data) if (v > m) m = v;
return m;
}
}
Tips:
- Kleine, duidelijke methoden zijn beter te testen en hergebruiken.
- Geef betekenisvolle namen aan methoden en parameters.
- Overload niet te veel; voorkom verwarring.
Koppeling met oefeningen:
- Zie
java-workbook/src/chapter_9.mdvoor methoden- en parameteropdrachten. - Uitwerkingen in
java-solutions/src/chapter_9.md.
Hoofdstuk 10 — Arrays en Strings (reeksen van gegevens en tekstbewerking)
In dit hoofdstuk leer je hoe je met meerdere waarden tegelijk werkt via arrays, en hoe je Strings effectief gebruikt en manipuleert. We bespreken declaratie, indexering, iteratie, veelgebruikte methoden en valkuilen (zoals out-of-bounds en immutability).
Voorbeeld 1 — Array declareren en gebruiken
public class ArrayBasis {
public static void main(String[] args) {
int[] cijfers = {7, 8, 9};
System.out.println(cijfers[0]); // 7
System.out.println(cijfers.length); // 3
}
}
Voorbeeld 2 — Array itereren (for en foreach)
public class ArrayIteratie {
public static void main(String[] args) {
String[] namen = {"Kim", "Bo", "Saar"};
for (int i = 0; i < namen.length; i++) {
System.out.println(i + ": " + namen[i]);
}
for (String n : namen) {
System.out.println(n);
}
}
}
Voorbeeld 3 — Arrays vullen en standaardwaarden
public class ArrayVullen {
public static void main(String[] args) {
int[] arr = new int[5]; // standaardwaarden 0
for (int i = 0; i < arr.length; i++) {
arr[i] = i * i;
}
for (int v : arr) System.out.println(v);
}
}
Voorbeeld 4 — Out-of-bounds fout
public class OutOfBoundsDemo {
public static void main(String[] args) {
int[] a = {1, 2, 3};
// System.out.println(a[3]); // ArrayIndexOutOfBoundsException
}
}
Voorbeeld 5 — String basis en immutability
public class StringBasis {
public static void main(String[] args) {
String tekst = "Java";
System.out.println(tekst.length());
System.out.println(tekst.toUpperCase());
System.out.println(tekst); // tekst blijft "Java"
}
}
Voorbeeld 6 — String methoden (substring, contains, replace)
public class StringMethoden {
public static void main(String[] args) {
String s = "Programmeren in Java";
System.out.println(s.substring(0, 12)); // "Programmeren"
System.out.println(s.contains("Java"));
System.out.println(s.replace("Java", "Kotlin"));
}
}
Voorbeeld 7 — String vergelijken en trimmen
public class StringVergelijkingEnTrim {
public static void main(String[] args) {
String a = " java ";
String b = "Java";
System.out.println(a.trim().equalsIgnoreCase(b)); // true
}
}
Voorbeeld 8 — StringBuilder voor efficiënte concatenatie
public class StringBuilderConcat {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 5; i++) sb.append(i).append(", ");
System.out.println(sb.toString());
}
}
Voorbeeld 9 — Arrays utility (java.util.Arrays)
import java.util.Arrays;
public class ArraysUtilities {
public static void main(String[] args) {
int[] a = {3, 1, 2};
Arrays.sort(a);
System.out.println(Arrays.toString(a));
int idx = Arrays.binarySearch(a, 2);
System.out.println("index van 2: " + idx);
}
}
Tips:
- Onthoud dat array-indexen bij 0 beginnen en eindigen bij
length - 1. - Strings zijn immutable; gebruik StringBuilder bij veel concatenaties in lussen.
- Pas op met
substring-indices; ze zijn halfopen:[begin, eind).
Koppeling met oefeningen:
- Zie
java-workbook/src/chapter_10.mdvoor arrays- en stringoefeningen. - Uitwerkingen in
java-solutions/src/chapter_10.md.
Hoofdstuk 11 — OOP: Klassen en Objecten (basis van objectgeoriënteerd denken)
In dit hoofdstuk maak je de stap van losse functies en gegevens naar samenhangende eenheden: objecten. Je leert wat klassen en objecten zijn, hoe je velden en methoden definieert, hoe constructors werken, wat this doet, en waarom inkapseling (encapsulation) met getters/setters nuttig is. We bekijken ook toString, equals/hashCode en geven praktische tips.
Voorbeeld 1 — Een eenvoudige klasse met veld en methode
class Persoon {
String naam; // veld (instantievariabele)
void groet() { // instantie-methode
System.out.println("Hallo, " + naam);
}
}
public class Demo1 {
public static void main(String[] args) {
Persoon p = new Persoon(); // object maken
p.naam = "Saar"; // veld rechtstreeks zetten (later: encapsuleren)
p.groet(); // methode aanroepen
}
}
Voorbeeld 2 — Constructor voor verplichte initialisatie
class Punt {
int x, y;
Punt(int x, int y) { // constructor
this.x = x; // this verwijst naar het huidige object
this.y = y;
}
}
public class Demo2 {
public static void main(String[] args) {
Punt p = new Punt(3, 4);
System.out.println("(" + p.x + ", " + p.y + ")");
}
}
Voorbeeld 3 — Encapsulation met private velden en getters/setters
class BankRekening {
private String iban; // afschermen voor directe toegang
private double saldo;
public BankRekening(String iban) {
this.iban = iban;
}
public String getIban() { return iban; }
public double getSaldo() { return saldo; }
public void stort(double bedrag) {
if (bedrag <= 0) throw new IllegalArgumentException("Bedrag moet > 0");
saldo += bedrag;
}
public void neemOp(double bedrag) {
if (bedrag <= 0 || bedrag > saldo) throw new IllegalArgumentException("Ongeldig bedrag");
saldo -= bedrag;
}
}
public class Demo3 {
public static void main(String[] args) {
BankRekening r = new BankRekening("NL00BANK0123456789");
r.stort(100);
r.neemOp(30);
System.out.println("Saldo: " + r.getSaldo());
}
}
Voorbeeld 4 — toString() voor leesbare weergave
class Product {
private final String naam;
private final double prijs;
Product(String naam, double prijs) {
this.naam = naam; this.prijs = prijs;
}
@Override public String toString() {
return "Product{" + "naam='" + naam + '\'' + ", prijs=" + prijs + '}';
}
}
public class Demo4 {
public static void main(String[] args) {
System.out.println(new Product("Mok", 7.95));
}
}
Voorbeeld 5 — equals en hashCode voor waardevergelijking
import java.util.Objects;
class Kaart {
private final String soort; // bijv. harten, schoppen
private final String rang; // bijv. boer, vrouw, aas
Kaart(String soort, String rang) {
this.soort = soort; this.rang = rang;
}
@Override public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Kaart kaart = (Kaart) o;
return Objects.equals(soort, kaart.soort) && Objects.equals(rang, kaart.rang);
}
@Override public int hashCode() {
return Objects.hash(soort, rang);
}
}
public class Demo5 {
public static void main(String[] args) {
System.out.println(new Kaart("harten", "aas").equals(new Kaart("harten", "aas"))); // true
}
}
Voorbeeld 6 — Statische leden vs. instantieleden
class Teller {
static int aantalObjecten = 0; // gedeeld door alle instanties
int waarde; // per object verschillend
Teller(int waarde) {
this.waarde = waarde;
aantalObjecten++;
}
}
public class Demo6 {
public static void main(String[] args) {
Teller a = new Teller(1);
Teller b = new Teller(2);
System.out.println(Teller.aantalObjecten); // 2
System.out.println(a.waarde + ", " + b.waarde);
}
}
Voorbeeld 7 — Samenspel van objecten (compositie)
class Adres { String straat; String stad; Adres(String straat, String stad){this.straat=straat;this.stad=stad;} }
class Klant {
String naam;
Adres adres; // Klant heeft een Adres
Klant(String naam, Adres adres) { this.naam = naam; this.adres = adres; }
}
public class Demo7 {
public static void main(String[] args) {
Adres a = new Adres("Laan 1", "Utrecht");
Klant k = new Klant("Kim", a);
System.out.println(k.naam + " uit " + k.adres.stad);
}
}
Voorbeeld 8 — Method chaining en builder-achtig patroon
class BerichtBuilder {
private final StringBuilder sb = new StringBuilder();
BerichtBuilder voegToe(String s) { sb.append(s); return this; }
String build() { return sb.toString(); }
}
public class Demo8 {
public static void main(String[] args) {
String bericht = new BerichtBuilder().voegToe("Hallo").voegToe(", ").voegToe("wereld").build();
System.out.println(bericht);
}
}
Veelgemaakte fouten en tips:
- Gebruik
privatevoor velden en exposeer gedrag via methoden; vermijd publieke velden tenzij goede reden. - Vergeet
thisniet wanneer parameternaam gelijk is aan veldnaam. - Herdefinieer
toStringvoor debugbaarheid; overweegequals/hashCodevoor waardeobjecten. - Maak onveranderlijke (immutable) objecten waar mogelijk: gebruik
finalvelden en geen setters.
Koppeling met oefeningen:
- Zie
java-workbook/src/chapter_11.mdvoor opdrachten over klassen/objecten, constructors en encapsulation. - Uitwerkingen staan in
java-solutions/src/chapter_11.mden bijbehorende .java-bestanden.
Hoofdstuk 12 — Overerving en Polymorfisme (hergebruik via hiërarchieën)
In dit hoofdstuk leer je hoe klassen kunnen erven van elkaar (extends), hoe je gedrag overschrijft (override), en hoe polymorfisme werkt via een gemeenschappelijk basistype. We bespreken ook super, final, abstracte klassen en interfaces, en tonen moderne patronen zoals pattern matching met instanceof.
Voorbeeld 1 — Basis overerving en overriding
class Dier { void maakGeluid() { System.out.println("..."); } }
class Hond extends Dier { @Override void maakGeluid() { System.out.println("Woef"); } }
class Kat extends Dier { @Override void maakGeluid() { System.out.println("Miauw"); } }
public class Demo12_1 {
public static void main(String[] args) {
Dier d1 = new Hond();
Dier d2 = new Kat();
d1.maakGeluid();
d2.maakGeluid();
}
}
Voorbeeld 2 — Polymorfisme in een methode
class GeluidPrinter {
static void printGeluid(Dier d) { d.maakGeluid(); }
}
public class Demo12_2 {
public static void main(String[] args) {
GeluidPrinter.printGeluid(new Hond());
GeluidPrinter.printGeluid(new Kat());
}
}
Voorbeeld 3 — super gebruiken
class Vorm {
String naam;
Vorm(String naam) { this.naam = naam; }
String beschrijf() { return "Vorm: " + naam; }
}
class Cirkel extends Vorm {
double r;
Cirkel(double r) { super("Cirkel"); this.r = r; }
@Override String beschrijf() { return super.beschrijf() + ", r=" + r; }
}
public class Demo12_3 {
public static void main(String[] args) {
System.out.println(new Cirkel(2.5).beschrijf());
}
}
Voorbeeld 4 — final om override te voorkomen
class Basis { final void nietOverschrijven() { System.out.println("vast gedrag"); } }
class Afgeleid extends Basis { /* kan niet overriden */ }
Voorbeeld 5 — Abstracte klasse en concrete subklassen
abstract class Figuur {
abstract double oppervlakte();
}
class Rechthoek extends Figuur {
double b, h;
Rechthoek(double b, double h){ this.b = b; this.h = h; }
@Override double oppervlakte(){ return b * h; }
}
class Cirkel2 extends Figuur {
double r;
Cirkel2(double r){ this.r = r; }
@Override double oppervlakte(){ return Math.PI * r * r; }
}
public class Demo12_5 {
public static void main(String[] args) {
Figuur f = new Cirkel2(1);
System.out.println(f.oppervlakte());
}
}
Voorbeeld 6 — Interface en meerdere implementaties
interface Betaalbaar { void betaal(double bedrag); }
class KaartBetaling implements Betaalbaar { public void betaal(double bedrag){ System.out.println("Kaart: " + bedrag); } }
class ContantBetaling implements Betaalbaar { public void betaal(double bedrag){ System.out.println("Cash: " + bedrag); } }
public class Demo12_6 {
public static void main(String[] args) {
Betaalbaar b = new KaartBetaling();
b.betaal(12.50);
b = new ContantBetaling();
b.betaal(7.95);
}
}
Voorbeeld 7 — instanceof met pattern matching (moderne Java)
public class Demo12_7 {
static void beschrijf(Dier d) {
if (d instanceof Hond h) {
System.out.println("Hond gezien");
h.maakGeluid();
} else if (d instanceof Kat k) {
System.out.println("Kat gezien");
k.maakGeluid();
} else {
System.out.println("Onbekend dier");
}
}
public static void main(String[] args) {
beschrijf(new Hond());
beschrijf(new Kat());
}
}
Voorbeeld 8 — @Override annotatie helpt fouten voorkomen
class Basis2 { void doeIets() {} }
class Afleid2 extends Basis2 { @Override void doeIets() { System.out.println("ok"); } }
Tips:
- Gebruik overerving spaarzaam; prefereer samenstelling ("has-a") boven overerving ("is-a") wanneer passend.
- Markeer methoden/klassen
finalals je extensie wil beperken. - Gebruik interfaces voor contracten en losjes gekoppelde ontwerpen.
Koppeling met oefeningen:
- Zie
java-workbook/src/chapter_12.mdvoor opdrachten rond overerving, interfaces en polymorfisme. - Uitwerkingen in
java-solutions/src/chapter_12.mden bijbehorende Java-bestanden.
Hoofdstuk 13 — Collecties en Generics (lijsten, verzamelingen en types)
Java biedt krachtige verzamelingen (collecties) zoals List, Set en Map. Met generics geef je type-informatie mee zodat je veiliger en leesbaarder code krijgt. In dit hoofdstuk leer je de basis en veelgebruikte patronen.
Voorbeeld 1 — List basis (ArrayList)
import java.util.*;
public class Demo13_1 {
public static void main(String[] args) {
List<String> namen = new ArrayList<>();
namen.add("Kim");
namen.add("Bo");
for (String n : namen) System.out.println(n);
}
}
Voorbeeld 2 — Set (unieke elementen)
import java.util.*;
public class Demo13_2 {
public static void main(String[] args) {
Set<Integer> set = new HashSet<>();
set.add(1); set.add(2); set.add(2);
System.out.println(set); // geen dubbelen
}
}
Voorbeeld 3 — Map (sleutel-waarde)
import java.util.*;
public class Demo13_3 {
public static void main(String[] args) {
Map<String, Integer> punten = new HashMap<>();
punten.put("Kim", 8);
punten.put("Bo", 7);
System.out.println(punten.get("Kim"));
}
}
Voorbeeld 4 — Itereren over Map entries
import java.util.*;
public class Demo13_4 {
public static void main(String[] args) {
Map<String, Integer> m = Map.of("a",1, "b",2);
for (Map.Entry<String,Integer> e : m.entrySet()) {
System.out.println(e.getKey() + " -> " + e.getValue());
}
}
}
Voorbeeld 5 — Sorteren met Comparator
import java.util.*;
public class Demo13_5 {
public static void main(String[] args) {
List<String> l = new ArrayList<>(List.of("Saar","Bo","Kim"));
l.sort(Comparator.naturalOrder());
System.out.println(l);
l.sort(Comparator.comparingInt(String::length));
System.out.println(l);
}
}
Voorbeeld 6 — Generieke methode
import java.util.*;
public class Demo13_6 {
static <T> void printAlle(Collection<T> c) {
for (T t : c) System.out.println(t);
}
public static void main(String[] args) {
printAlle(List.of(1,2,3));
printAlle(Set.of("a","b"));
}
}
Voorbeeld 7 — Eigen generieke klasse (paar)
class Paar<A,B> {
final A links; final B rechts;
Paar(A links, B rechts){ this.links = links; this.rechts = rechts; }
}
public class Demo13_7 {
public static void main(String[] args) {
Paar<String,Integer> p = new Paar<>("x", 10);
System.out.println(p.links + ":" + p.rechts);
}
}
Voorbeeld 8 — List vs LinkedList kort, en prestaties
// ArrayList: snelle random access, trager invoegen middenin.
// LinkedList: snel invoegen/verwijderen aan randen, trage random access.
Voorbeeld 9 — Veelgebruikte hulpfuncties
import java.util.*;
public class Demo13_9 {
public static void main(String[] args) {
List<Integer> l = new ArrayList<>(List.of(3,1,2));
Collections.sort(l);
System.out.println(l);
Collections.reverse(l);
System.out.println(l);
}
}
Tips:
- Gebruik generics consequent:
List<String>i.p.v. rawList. - Kies de juiste collectie voor de taak (uniek? volgorde? snelle zoekopdrachten?).
- Gebruik
Comparatorvoor sorteerlogica buiten je modelklassen.
Koppeling met oefeningen:
- Zie
java-workbook/src/chapter_13.mdvoor opdrachten met List/Set/Map en generics. - Uitwerkingen in
java-solutions/src/chapter_13.mden Java-bestanden.
Hoofdstuk 14 — Foutenafhandeling (Exceptions) (robuste programma’s)
Exceptions signaleren uitzonderlijke situaties. In dit hoofdstuk leer je try/catch/finally, checked vs unchecked, throw/throws, multi-catch en try-with-resources.
Voorbeeld 1 — Basis try/catch/finally
public class Demo14_1 {
public static void main(String[] args) {
try {
int x = 5 / 0;
} catch (ArithmeticException ex) {
System.out.println("Fout: " + ex.getMessage());
} finally {
System.out.println("Altijd uitgevoerd");
}
}
}
Voorbeeld 2 — Meerdere catches en volgorde
public class Demo14_2 {
public static void main(String[] args) {
try {
Integer.parseInt("abc");
} catch (NumberFormatException nfe) {
System.out.println("Geen getal");
} catch (RuntimeException re) {
System.out.println("Runtime: " + re);
}
}
}
Voorbeeld 3 — Multi-catch
public class Demo14_3 {
public static void main(String[] args) {
try {
if (args.length == 0) throw new IllegalArgumentException("geen args");
String s = null; s.length();
} catch (IllegalArgumentException | NullPointerException ex) {
System.out.println("Probleem: " + ex.getClass().getSimpleName());
}
}
}
Voorbeeld 4 — throw en throws
class Checker {
static void checkLeeftijd(int l) throws Exception {
if (l < 18) throw new Exception("Te jong"); // checked exception
}
}
public class Demo14_4 {
public static void main(String[] args) {
try {
Checker.checkLeeftijd(15);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Voorbeeld 5 — Aangepaste (custom) exception
class OngeldigBedragException extends RuntimeException {
OngeldigBedragException(String msg){ super(msg); }
}
class Rekening {
double saldo;
void neemOp(double bedrag) {
if (bedrag <= 0 || bedrag > saldo) throw new OngeldigBedragException("Bedrag ongeldig");
saldo -= bedrag;
}
}
Voorbeeld 6 — Try-with-resources (sluit automatisch)
import java.io.*;
public class Demo14_6 {
public static void main(String[] args) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader("input.txt"))) {
System.out.println(br.readLine());
}
}
}
Voorbeeld 7 — Re-throw en context behouden
public class Demo14_7 {
static void doeIets() {
try {
throw new IllegalStateException("kapot");
} catch (IllegalStateException ex) {
throw new RuntimeException("Higher-level context", ex);
}
}
}
Voorbeeld 8 — Defensieve programmeren en validatie
public class Demo14_8 {
static int somNietNull(Integer a, Integer b) {
if (a == null || b == null) throw new IllegalArgumentException("a/b mag niet null zijn");
return a + b;
}
}
Tips:
- Vang alleen exceptions die je daadwerkelijk kunt afhandelen. Laat de rest doorstijgen.
- Plaats zo klein mogelijke
try-blokken, enkel rond code die kan falen. - Gebruik
try-with-resourcesvoor I/O zodat resources altijd gesloten worden.
Koppeling met oefeningen:
- Zie
java-workbook/src/chapter_14.mdvoor opdrachten met try/catch en custom exceptions. - Uitwerkingen in
java-solutions/src/chapter_14.mden Java-bestanden.
Hoofdstuk 15 — Best Practices en Volgende Stappen (slimmer en schoner bouwen)
In dit slothoofdstuk bundelen we richtlijnen die je code leesbaar, onderhoudbaar en robuust maken. Ook geven we suggesties voor je verdere leerpad.
Onderwerp 1 — Kleine, duidelijke functies en SRP
- Hou methoden klein en met één duidelijke verantwoordelijkheid (Single Responsibility Principle).
- Splits lange methoden op; geef methoden/klassen betekenisvolle namen.
Voorbeeld — Refactor naar helpermethode
public class BestPractice1 {
static boolean isEven(int n) { return n % 2 == 0; }
public static void main(String[] args) {
System.out.println(isEven(4));
}
}
Onderwerp 2 — Immutability waar het kan
- Gebruik
finalvelden en maak objecten onveranderlijk als dat logisch is. - Minder onverwachte bijwerkingen, simpeler te redeneren.
Onderwerp 3 — Foutenafhandeling met intentie
- Vang alleen wat je kunt oplossen; log context; gebruik betekenisvolle berichten.
- Gebruik
try-with-resourcesvoor I/O.
Onderwerp 4 — Naamgeving en stijl
- Consistente conventies: camelCase voor variabelen/methoden, PascalCase voor klassen.
- Vermijd afkortingen; kies duidelijkheid boven kortheid.
Onderwerp 5 — Testen en debugging
- Schrijf kleine testjes (desnoods met
main) om gedrag te verifiëren. - Gebruik logging of prints spaarzaam; overweeg later JUnit.
Onderwerp 6 — Prestaties en complexiteit
- Kies de juiste datastructuur (ArrayList vs LinkedList; HashMap vs TreeMap).
- Optimaliseer pas na meting; leesbaarheid eerst.
Onderwerp 7 — Documentatie
- Gebruik JavaDoc bij publiek API-oppervlak.
- Schrijf README’s en commentaar op niet-triviale delen.
Vervolgonderwerpen om te leren
- Packages en modules (structuur van grotere projecten)
- In- en uitvoer (NIO.2), bestandsverwerking
- Lambdas en Streams (functionele stijl voor collecties)
- Concurrency (threads, executors, synchronized, concurrent collections)
- Unit testing met JUnit; build tools (Maven/Gradle)
Oefeningen en projecten
- Bouw een kleine console-app (bijv. todo-lijst) en pas best practices toe.
- Herstructureer eerdere oefeningen met encapsulation, toString en tests.
Koppeling
- Oefeningen:
java-workbook/src/chapter_15.md - Uitwerkingen:
java-solutions/src/chapter_15.md