Version without JavaScript, read-only: workshops, quizzes and running code are not available here. Full version · Catalogue · Sign in
Lecture notes · chapter 9
Exceptions
What happens to execution when an operation fails, the difference between checked and unchecked exceptions, and the common ways of hiding an error unintentionally.
This chapter extends sequences 7, 8 and 9.
Return codes and exceptions
int prix = canard.getPrix();
if (prix == -1) { /* error? or a free duck? */ }
An error code can be confused with a valid value, it can be ignored without anything reporting it, and it has to be passed on by hand from one caller to the next. An exception interrupts the normal course of the program, carries a message, and cannot be ignored through simple oversight.
public void setPrix(int prix) {
if (prix < 0) throw new IllegalArgumentException("prix >= 0");
this.prix = prix;
}
throw interrupts the method immediately: the following statements are not executed.
try, catch, finally
try {
CanardEnPlastique c = new CanardEnPlastique("Jean", -50);
System.out.println("jamais atteint");
} catch (IllegalArgumentException e) {
System.out.println("Erreur : " + e.getMessage());
} finally {
System.out.println("toujours exécuté : on vide le bassin");
}
trycontains the normal processing;catchsays what to do on failure, depending on the type of exception;finallycontains the clean-up, executed in every case: success, failure, and even after areturn.
return in a finally
Before running the program, try to predict what lireProfondeur() returns and what becomes of the exception.
Finally.java
class Bassin {
/** A measurement that fails. */
static int mesurer() {
throw new IllegalStateException("sonde débranchée");
}
/** Faulty version: a return in the finally. */
static int lireProfondeur() {
try {
return mesurer();
} finally {
return -1; // ← swallows everything
}
}
/** Faulty version no. 2: the catch that says nothing. */
static int lireTemperature() {
try {
return mesurer();
} catch (Exception e) {
return 0; // the error has left no trace
}
}
/** Correct version: we clean up, we do not decide in the caller's place. */
static int lireCorrectement() {
try {
return mesurer();
} finally {
System.out.println(" (nettoyage : sonde remise en place)");
}
}
public static void main(String[] args) {
System.out.println("1. lireProfondeur() = " + lireProfondeur());
System.out.println("2. lireTemperature() = " + lireTemperature());
System.out.println("3. lireCorrectement() :");
try {
System.out.println(" valeur = " + lireCorrectement());
} catch (IllegalStateException e) {
System.out.println(" l'exception est bien remontée : " + e.getMessage());
}
}
}
A workshop goes here: you write and run code in it. It requires JavaScript.
Checked or unchecked
classDiagram
direction TB
class Throwable
class Error["Error (JVM problems)"]
class Exception
class RuntimeException["RuntimeException (unchecked)"]
class IOException["IOException (checked)"]
class NullPointerException
class IllegalArgumentException
Throwable <|-- Error
Throwable <|-- Exception
Exception <|-- RuntimeException
Exception <|-- IOException
RuntimeException <|-- NullPointerException
RuntimeException <|-- IllegalArgumentExceptionFor a checked exception, the compiler requires it to be declared (throws) or handled (catch). It signals an external event that a correct program must anticipate, such as a missing file or a network outage.
For an unchecked exception, the compiler requires nothing. It signals that an invariant does not hold, that is, a bug: an invalid argument, a null reference.
Defining your own exception
public class PrixCanardException extends Exception {
public PrixCanardException(String message) { super(message); }
}
public void setPrix(int prix) throws PrixCanardException {
if (prix < 0) throw new PrixCanardException("Prix négatif interdit !");
this.prix = prix;
}
With extends Exception, the exception is checked and the caller will have to handle it; with extends RuntimeException, it is unchecked. The parent class determines the category: there is no keyword for it.
A named business exception is preferable to a generic IllegalArgumentException, because it can be caught separately and its name indicates what happened.
Hiding an error unintentionally
Good practice
- Catch the precise exception type, not
Exceptionfor convenience. - Write a useful message, stating what was expected and what was received. A message such as
"Erreur"does not help find the problem. - Keep the cause by passing it to the constructor:
throw new TraitementException("import du bassin", e), with thee. - Do not use exceptions to control the course of the program: leaving a loop with a
throw, for example, is a misuse.
Exam question
What is the difference between a checked and an unchecked exception?
A checked exception must be declared or handled, otherwise the compiler rejects the code; it signals a foreseeable external event. An unchecked exception (RuntimeException and its subclasses) imposes nothing and signals a programming error. The category depends on the parent class.