Inloggen
Inloggen

Uitzonderingen in Java vangen en afhandelen

Uitzonderingen in Java vangen en afhandelen
Hostman Team
Technical writer
Programmeertaal Java
24.10.2025
Reading time: 12 min

De programmeertaal Java beschikt, net als veel andere talen, over ingebouwde hulpmiddelen om met fouten om te gaan, oftewel uitzonderlijke situaties (exceptions), waarbij een programmastoring wordt behandeld door speciale code die losstaat van het hoofdalgoritme.

Dankzij uitzonderingen kan een ontwikkelaar zwakke punten in de code voorzien en fatale fouten tijdens runtime voorkomen.

Daarom is het afhandelen van uitzonderingen in Java een goede praktijk die de algehele betrouwbaarheid van de code verbetert.

Het doel van dit artikel is de principes van het vangen en afhandelen van uitzonderingen te onderzoeken en de bijbehorende syntactische structuren van de taal te bekijken die hiervoor bedoeld zijn.

Alle voorbeelden in deze handleiding zijn uitgevoerd op Ubuntu 22.04, geïnstalleerd op een cloudserver van Hostman.

OpenJDK installeren en een toepassing uitvoeren

De voorbeelden in deze handleiding zijn uitgevoerd met OpenJDK. De installatie is eenvoudig.

Werk eerst de lijst met beschikbare repositories bij:

sudo apt update

Vraag vervolgens de lijst op van beschikbare OpenJDK-versies:

sudo apt search openjdk | grep -E 'openjdk-.*-jdk/'

U ziet een korte lijst in de terminal:

WARNING: apt does not have a stable CLI interface. Use with caution in scripts.
openjdk-11-jdk/jammy-updates,jammy-security 11.0.25+9-1ubuntu1~22.04 amd64  
openjdk-17-jdk/jammy-updates,jammy-security 17.0.13+11-2ubuntu1~22.04 amd64  
openjdk-18-jdk/jammy-updates,jammy-security 18.0.2+9-2~22.04 amd64  
openjdk-19-jdk/jammy-updates,jammy-security 19.0.2+7-0ubuntu3~22.04 amd64  
openjdk-21-jdk/jammy-updates,jammy-security,now 21.0.5+11-1ubuntu1~22.04 amd64 [installed]  
openjdk-8-jdk/jammy-updates,jammy-security 8u432-ga~us1-0ubuntu2~22.04 amd64  

We gebruiken de versie openjdk-21-jdk:

sudo apt install openjdk-21-jdk

Controleer daarna of Java correct is geïnstalleerd door de versie op te vragen:

java --version

De terminaloutput zal er ongeveer zo uitzien:

openjdk 21.0.5 2024-10-15  
OpenJDK Runtime Environment (build 21.0.5+11-Ubuntu-1ubuntu122.04)  
OpenJDK 64-Bit Server VM (build 21.0.5+11-Ubuntu-1ubuntu122.04, mixed mode, sharing)

Zoals te zien is, is de exacte versie van OpenJDK 21.0.5.

Alle voorbeelden in deze handleiding moeten worden opgeslagen in een apart bestand met de extensie .java:

nano App.java

Vul het gemaakte bestand met voorbeeldcode zoals deze:

class App {
	public static void main(String[] args) {
		System.out.println("This text is printed to the console");
	}
}

Let erop dat de naam van de klasse overeenkomt met de bestandsnaam.

Compileer vervolgens het bestand:

javac App.java

En voer het uit:

java App

De terminal toont het volgende:

This text is printed to the console

Typen uitzonderingen in Java

Alle uitzonderingen in Java hebben een specifiek type dat is gekoppeld aan de reden waarom de uitzondering optrad — het specifieke soort programmastoring.

Er zijn twee fundamentele typen uitzonderingen:

  • Checked Exceptions — treden op tijdens de compilatie. Als ze niet worden afgehandeld, wordt het programma niet gecompileerd.
  • Unchecked Exceptions — treden op tijdens de uitvoering. Als ze niet worden afgehandeld, wordt het programma beëindigd.

Het type Error wordt slechts voorwaardelijk als uitzondering beschouwd — het is een volwaardige fout die onvermijdelijk tot een crash van het programma leidt.

Uitzonderingen die met aangepaste code kunnen worden afgehandeld en het programma laten doorgaan, zijn Checked Exceptions en Unchecked Exceptions.

Daarom zijn fouten en uitzonderingen in Java verschillende entiteiten. Zowel Errors als Exceptions (Checked en Unchecked) zijn typen met aanvullende subtypen die de oorzaak van de storing verduidelijken.

Checked Exceptions

Hier is een voorbeeld van code die een compile-tijduitzondering veroorzaakt:

import java.io.File;
import java.util.Scanner;

public class App {
	public static void main(String[] args) {
		File someFile = new File("someFile.txt"); // maak een bestandsreferentie
        Scanner scanner = new Scanner(someFile);  // parse de bestandsinhoud
    }
}

De compilatie wordt onderbroken en u ziet de volgende fout in de terminal:

App.java:7: error: unreported exception FileNotFoundException; must be caught or declared to be thrown  
                Scanner scanner = new Scanner(someFile);  
                                  ^  
1 error

Als u deze uitzondering opvangt en afhandelt, wordt de code gecompileerd en uitvoerbaar.

Unchecked Exceptions

Hier is nog een voorbeeld van code die pas tijdens runtime een uitzondering veroorzaakt:

class App {
	public static void main(String[] args) {
		int[] someArray = {1, 2, 3, 4, 5}; // maak een array met 5 elementen
        System.out.println(someArray[10]); // poging om een niet-bestaand element te benaderen
    }
}

Tijdens de compilatie treedt geen uitzondering op, maar na het uitvoeren van de gecompileerde code ziet u deze fout in de terminal:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 5  
	at app.main(app.java:4)

Dit betekent dat een dergelijke uitzondering kan worden afgehandeld met door de gebruiker gedefinieerde code, waardoor het programma kan doorgaan met uitvoeren.

Error

Tot slot, hier is een voorbeeld van code die een runtimefout veroorzaakt:

public class App {
	static int i = 0;

	public static int showSomething(int x) {
		i = i + 2;
		return i + showSomething(i + 2);
	}

	public static void main(String[] args) {
		App.showSomething(i); // trigger stack overflow
	}
}

De compilatie zal slagen, maar tijdens de uitvoering zal de terminal een StackOverflowError tonen:

Exception in thread "main" java.lang.StackOverflowError  
	at java.base/java.io.BufferedOutputStream.implWrite(BufferedOutputStream.java:220)  
	at java.base/java.io.BufferedOutputStream.write(BufferedOutputStream.java:200)  
	at java.base/java.io.PrintStream.implWrite(PrintStream.java:643)

In dit geval kan de fout niet worden afgehandeld; deze kan alleen in de code worden opgelost.

Exceptieklassen in Java

Intern worden alle uitzonderingen (en fouten) in Java weergegeven als een verzameling klassen, waarvan sommige van andere erven.

De basisklasse voor alle fouten en uitzonderingen is Throwable. Twee andere klassen erven hiervan: Error en Exception, die dienen als basisklassen voor een breed scala aan subklassen die zijn gekoppeld aan specifieke uitzonderingen.

De klasse Error beschrijft fouten van het type systeemfout, terwijl de klasse Exception gecontroleerde uitzonderingen beschrijft.

Bovendien erft de klasse RuntimeException van Exception en beschrijft ongecontroleerde uitzonderingen.

Een vereenvoudigde hiërarchie van Java-uitzonderingen kan als volgt worden weergegeven:

  • Throwable

    • Error

    • Exception

      • CloneNotSupportedException

      • InterruptedException

      • ReflectiveOperationException

        • ClassNotFoundException

        • IllegalAccessException

        • InstantiationException

        • NoSuchFieldException

        • NoSuchMethodException

      • RuntimeException

        • NullPointerException

        • ArithmeticException

        • IllegalArgumentException

        • IndexOutOfBoundException

        • NumberFormatException

Elke exceptieklasse bevat methoden om extra informatie over de fout op te vragen.

De volledige classificatie van Java-uitzonderingen, inclusief die uit aanvullende pakketten, vindt u in de officiële referentiegids.

Syntaxis voor foutafhandeling in Java

try en catch

Alle uitzonderingen worden afgehandeld met speciale try- en catch-blokken, die standaard zijn in de meeste programmeertalen, inclusief Java.

Binnen het try-blok schrijft u code die mogelijk een fout bevat die een uitzondering kan veroorzaken.

Binnen het catch-blok schrijft u code die de uitzondering afhandelt die in het vooraf gedefinieerde try-blok is opgetreden.

Bijvoorbeeld, een try-catch-structuur ziet er als volgt uit:

public class App {
	public static void main(String[] args) {
		try {
			// code that might throw an exception
			int someVariable = 5 / 0;
			System.out.println("Who said you can’t divide by zero?");
		} catch (ArithmeticException someException) {
			// code that handles the exception
			System.out.println("Actually, you can't divide by zero...");
		}
	}
}

De uitvoer van deze code in de console zal zijn:

Actually, you can't divide by zero...

Dit voorbeeld is gebaseerd op een ongeldige deling door nul, verpakt in een try-blok dat een ArithmeticException genereert.

In het catch-blok wordt deze uitzondering afgehandeld door een foutmelding in de console af te drukken.

Dankzij deze structuur kan het programma blijven draaien, zelfs na een deling door nul.

finally

In tegenstelling tot veel andere programmeertalen bevat Java een speciaal finally-blok als onderdeel van het foutafhandelingsmechanisme. Het wordt altijd uitgevoerd — ongeacht of er een uitzondering is opgetreden of niet.

We kunnen dus de eerder getoonde structuur uitbreiden:

public class App {
	public static void main(String[] args) {
		try {
			// code that might throw an exception
			int someVariable = 5 / 0;
		} catch (ArithmeticException someException) {
			// code that handles the exception
			System.out.println("Actually, you can't divide by zero...");
		} finally {
			// code that always executes
			System.out.println("Who cares if you can divide by zero or not? This message will appear anyway!");
		}
	}
}

Na het uitvoeren van deze code toont de console:

Actually, you can't divide by zero...
Who cares if you can divide by zero or not? This message will appear anyway!

Om het praktische nut van het finally-blok te begrijpen, bekijk het volgende voorbeeld:

try {
	parseJson(response.json);
} catch (JSONException someException) {
	System.out.println("Looks like there’s something wrong with the JSON...");
}

// a function that hides the loading indicator
hideLoaderUI();

In een programma met deze structuur wordt de functie hideLoaderUI() nooit uitgevoerd als er een uitzondering optreedt.

U kunt proberen hideLoaderUI() zowel in de foutafhandeling als daarna aan te roepen:

try {
	parseJson(response.json);
} catch (JSONException someException) {
	hideLoaderUI(); // duplicate
	System.out.println("Looks like there’s something wrong with the JSON...");
}

hideLoaderUI(); // duplicaat

Dit leidt echter tot ongewenste duplicatie van de functieaanroep. Bovendien wordt het dupliceren van code als slechte praktijk beschouwd.

Om ervoor te zorgen dat hideLoaderUI() in elk geval wordt uitgevoerd zonder duplicatie, kunt u een finally-blok gebruiken:

try {
	parseJson(response.json);
} catch (JSONException someException) {
	System.out.println("Looks like there’s something wrong with the JSON...");
} finally {
	// the loading indicator will be hidden in any case
	hideLoaderUI();
}

throw

Java maakt het mogelijk om handmatig uitzonderingen te genereren (gooien) met de speciale operator throw:

public class App {
	public static void main(String[] args) {
		throw new Exception("Something strange seems to have happened...");
	}
}

U kunt zelfs een variabele voor de uitzondering van tevoren aanmaken en deze vervolgens gooien:

public class App {
	public static void main(String[] args) {
		var someException = new Exception("Something strange seems to have happened...");
		throw someException;
	}
}

throws

Een ander belangrijk trefwoord, throws (met een "s" aan het einde), maakt het mogelijk om expliciet de typen uitzonderingen te declareren (in de vorm van klassenamen) die een methode kan genereren.

Als een dergelijke methode een uitzondering genereert, wordt deze doorgegeven aan de aanroepende code, die deze moet afhandelen:

public class App {
	public static void someMethod() throws ArithmeticException, NullPointerException, InterruptedException {
		int someVariable = 5 / 0;
	}

	public static void main(String[] args) {
		try {
			App.someMethod();
		} catch (Exception someException) {
			System.out.println("Dividing by zero again? Do you even know what insanity is?");
		}
	}
}

De console-uitvoer zal zijn:

Dividing by zero again? Do you even know what insanity is?

Aangepaste uitzonderingen maken

De hiërarchische structuur van uitzonderingen maakt het mogelijk aangepaste exceptieklassen te maken die erven van de basisklassen.

Dankzij aangepaste uitzonderingen kunt u in Java specifieke foutafhandelingspaden voor uw toepassing implementeren.

Naast de standaard Java-uitzonderingen kunt u dus uw eigen toevoegen.

Elke aangepaste uitzondering kan, net als een vooraf gedefinieerde, worden afgehandeld met de standaard try-catch-finally-blokken:

class MyOwnException extends Exception {
	public MyOwnException(String message) {
		super(message); // roept de constructor van de bovenliggende klasse aan
        System.out.println("Warning! An exception is about to be thrown!");
	}
}

public class App {
	public static void main(String[] args) {
		try {
			throw new MyOwnException("Just an exception. No explanation. Anyone got a problem?");
		} catch (MyOwnException someException) {
			System.out.println(someException.getMessage());
		}
	}
}

Console-uitvoer:

Warning! An exception is about to be thrown!
Just an exception. No explanation. Anyone got a problem?

Conclusie

Deze handleiding heeft met voorbeelden laten zien waarom uitzonderingen in Java nodig zijn, hoe ze ontstaan (inclusief handmatig genereren) en hoe ze kunnen worden afgehandeld met de bijbehorende taalhulpmiddelen.

Uitzonderingen die kunnen worden opgevangen en afgehandeld zijn er in twee typen:

  • Checked Exceptions: afgehandeld tijdens compilatie.

  • Unchecked Exceptions: afgehandeld tijdens runtime.

Daarnaast zijn er fatale fouten die alleen kunnen worden opgelost door de code te herschrijven:

  • Errors: kunnen niet worden afgehandeld.

Er zijn verschillende syntactische structuren (blokken) voor foutafhandeling:

  • try: code die een uitzondering kan genereren.

  • catch: code die de mogelijke uitzondering afhandelt.

  • finally: code die altijd wordt uitgevoerd, ongeacht of er een uitzondering is opgetreden.

Daarnaast zijn er sleutelwoorden voor het beheren van het genereren van uitzonderingen:

  • throw: genereert handmatig een uitzondering.

  • throws: vermeldt de mogelijke uitzonderingen die een methode kan genereren.

De volledige lijst van methoden in de bovenliggende klasse Exception is te vinden in de officiële Oracle-documentatie.

Programmeertaal Java
24.10.2025
Reading time: 12 min

Vergelijkbaar

Heb je vragen,
opmerkingen of zorgen?

Onze professionals staan altijd klaar om je te helpen,
of je nu hulp nodig hebt of gewoon niet weet waar te beginnen
E-mail ons
Hostman's Support