Participer au site avec un Tip
Rechercher
 

Améliorations / Corrections

Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.

Emplacement :

Description des améliorations :

Introduction à la gestion des exceptions

Les classes scellées Mise en oeuvre d'une classe d'exception


Accès rapide :
La vidéo
Qu'est qu'une exception ?
On traite l'exception.
Le bloc d'instructions try.
Le bloc d'instructions catch.
Le mot clé finally.
On relaye l'exception.
Le mot clé throws
Vous devez, normalement, dire ce que vous faites de vos exceptions
Les exceptions et la documentation de votre code
On déclenche une exception avec l'instruction throw

La vidéo

Cette vidéo vous présente les concepts de base du traitement d'exception en Java. Une exception java représente un état « exceptionnel » d'exécution de votre programme : une erreur. Les mots clés try, catch, throw et throws vous sont présentés.


Introduction à la gestion des exceptions

Qu'est qu'une exception ?

Avant de rentrer dans les détails syntaxiques, je vais essayer de répondre à une première interrogation : qu'est qu'une exception ? Pour faire simple, une exception est une erreur produite durant l'exécution de votre programme. Sémantiquement parlant, le terme d'exception a été retenue car une erreur est censée être exceptionnelle : c'est n'est pas le mode de fonctionnement nominale de votre application.

dans certains cas, les développeurs utilisent le mécanisme d'exception pour représenter autre chose qu'une erreur (un cas de fonctionnement normal de l'application), mais ce type d'utilisation reste relativement marginal.

La chose la plus importante à comprendre c'est qu'en cas de déclenchement d'exception (d'erreur) le programme passe dans un mode d'exécution particulier : il faut qu'il trouve un gestionnaire d'erreur (un bloc d'instruction try / catch). Analysons le programme suivant. Via l'appel à la méthode Math.random, ce programme a une chance sur trois de déclencher une exception (à cause de la division par 0, qui rappelons le, n'est pas autorisée).

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
package fr.koor.exceptions;

public class TestException {

    public static void method3() {
        System.out.println( "BEGIN method3" );
        int divisor = (int) (Math.random() * 3);
        int value = 1 / divisor;
        System.out.println( "Value == " + value );
        System.out.println( "END method3" );
    }

    public static void method2() {
        System.out.println( "BEGIN method2" );
        method3();
        System.out.println( "END method2" );
    }
    
    public static void method1() {
        System.out.println( "BEGIN method1" );
        method2();
        System.out.println( "END method1" );
    }

    public static void main(String[] args) {
        System.out.println( "BEGIN main" );
        method1();
        System.out.println( "END main" );
    }

}
Exemple de déclenchement d'exception (via une division par 0)

Comme vous le constatez, ce programme met en oeuvre une chaîne d'appels de méthodes. Bien entendu, le point d'entrée est le main. Puis il invoque method1 qui invoque à son tour method2 et qui finit par invoquer method3. A chaque niveau on trace l'entrée dans la méthode ainsi de la sortie. Comme indiqué précédemment, là où les choses se corsent, c'est en ligne 8, car on produit une division par un entier qui peut valoir 0. Deux issues sont possibles pour ce programme.

Soit la valeur calculée aléatoirement vaut 1 ou 2 et dans ce cas, la division se passe correctement. Du coup, l'exécution du programme se passe de manière traditionnelle : voici les résultats affichés sur la console.

$> java fr.koor.exceptions.TestException
BEGIN main
BEGIN method1
BEGIN method2
BEGIN method3
Value == 0              ( ou 1, si divisor == 1)
END method3
END method2
END method1
END main$> 

Soit la valeur calculée aléatoirement vaut 0 et dans ce cas une exception est déclenchée. Une fois l'exception produite (on dit aussi que l'exception est levée) le système se met à la recherche d'un bloc de traitement d'erreur (un bloc try / catch). Le souci, c'est qu'il n'y a pas de tel bloc dans la méthode method3 : en conséquence l'exécution de la méthode est interrompue, et on se retrouve en ligne 15. Toutes les variables locales définis par method3 (ainsi que les éventuels paramètres de la méthode) sont détruites (on a dépilé au niveau de la stack). Mais nous sommes toujours en mode « exception levée » et donc le système cherche toujours à localiser un bloc try / catch. Il n'y en a pas non plus dans la méthode method2, donc on abandonne l'exécution de cette méthode et on dépile encore une fois. On se retrouve en ligne 21. Toujours pas de bloc try / catch. On sort aussi de cette méthode et on se retrouve en ligne 27. Toujours pas de try / catch et du coup on sort de la méthode main. Et là me direz-vous ?

Et bien, le programme est terminé ! La JVM a récupéré l'exception et elle l'affiche sur la console, mais après elle rend simplement la main. Le fait d'avoir suspendu l'exécution de toutes les méthodes garanti qu'aucun affichage de type END methodX ne sera produit. Voici un exemple d'exécution en cas de déclenchement d'exception.

$> java fr.koor.exceptions.TestException
BEGIN method1
BEGIN method2
BEGIN method3
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at fr.koor.exceptions.TestException.method3(TestException.java:8)
    at fr.koor.exceptions.TestException.method2(TestException.java:15)
    at fr.koor.exceptions.TestException.method1(TestException.java:21)
    at fr.koor.exceptions.TestException.main(TestException.java:27)
$> 

Donc c'est clair, il faut gérer les erreurs si vous ne voulez pas que votre programme s'arrête prématurément.

On traite l'exception.

Pour intercepter et traiter une exception, on utilise l'instruction try / catch / finally. Celle-ci peut être constituée d'un nombre variable de blocs d'instructions en sachant que certains sont facultatifs (un peu comme le bloc else dans une instruction if / else). Voici la syntaxe globale de l'instruction try / catch / finally.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
try {
            
    // Bloc d'instructions pouvant déclencher une erreur
    
} catch ( Exception exception ) {
    
    // Bloc d'instructions pour traiter une éventuelle exception
    
} finally {
    
    // Bloc d'instructions à exécuter dans tous les cas, 
    // que le try se soit exécuté en succès ou en erreur.
    
}
Syntaxe Globale de l'instruction try / catch / finally
contrairement aux autres instructions du langage Java, les accolades sont ici obligatoires. Si vous les oubliez, une erreur de compilation sera produite.

Le bloc d'instructions try.

Le bloc try permet de définir un ensemble d'instructions à surveiller : la traduction du mot try en français est « essayer ». Ce bloc est obligatoire. Il ne peut pas y avoir de bloc catch (ou finally) sans bloc try associé et les accolades y sont obligatoires.

Si une exception est déclenchée durant l'exécution du bloc try, il sera alors suspendu et l'exécution se poursuivra dans un bloc catch associé ou dans le bloc finally.

Le bloc d'instructions catch.

Il peut y avoir un ou plusieurs blocs catch associé à un bloc try. Chaque bloc catch est associé à un type d'erreur (une classe d'exception) à traiter : c'est ce qui est dit entre les parenthèses qui suivent le mot clé catch.

Si vous fournissez plusieurs blocs catch, ils devront alors être ordonnés du bloc le plus spécifique ou bloc le plus général. Si vous ne respectez pas l'ordre attendu, l'erreur de compilation suivante sera produite.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
try {
    BufferedReader reader = new BufferedReader(
        new InputStreamReader( System.in )
    );
    System.out.print( "Veuillez saisir un entier : " );
    String strValue =  reader.readLine();
    int value = Integer.parseInt( strValue );
    System.out.println( "Value == " + value );
} catch( Exception exception ) {
    System.out.println( "une exception quelconque" );
} catch( NumberFormatException exception ) {
    System.out.println( "La chaîne ne correspond pas à un entier" );
}
Blocs catch non correctement ordonnés

Pour produire l'erreur de compilation :

$> javac Sample.java
Sample.java:18: error: exception NumberFormatException has already been caught
        } catch( NumberFormatException exception ) {
          ^
1 error
$> 
le message précise que l'exception NumberFormatException est déjà attrapée. Effectivement, comme la classe java.lang.NumberFormatException dérive de la classe java.lang.Exception, elle est déjà gérée par le premier bloc catch associé au type Exception.

La bonne syntaxe est donc la suivante.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
try {
    BufferedReader reader = new BufferedReader(
        new InputStreamReader( System.in )
    );
    System.out.print( "Veuillez saisir un entier : " );
    String strValue =  reader.readLine();
    int value = Integer.parseInt( strValue );
    System.out.println( "Value == " + value );
} catch( NumberFormatException exception ) {
    System.out.println( "La chaîne ne correspond pas à un entier" );
} catch( Exception exception ) {
    System.out.println( "une exception quelconque" );
}
Blocs catch non correctement ordonnés

En cas de déclenchement d'exception, l'exécution du code est donc redirigée vers le bloc catch le plus adapté. Une fois le bloc catch terminé, le bloc try n'est pas rejoué. Si vous souhaitez que ce soit le cas, il vous appartient d'utiliser une boucle pour retenter l'exécution du bloc try. Voici un exemple de code tentant, au maximum trois fois, d'effectuer une saisie de valeur numérique entière.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class Sample {
    
    public static void main( String [] args ) {
        
        int value = 0;
        int tryMaxCount = 3;

        while( tryMaxCount > 0 ) {
            try {
                BufferedReader reader = new BufferedReader(
                    new InputStreamReader( System.in )
                );
                System.out.print( "Veuillez saisir un entier : " );
                String strValue =  reader.readLine();
                value = Integer.parseInt( strValue );
                break;  // Pour sortir de la boucle while
            } catch( NumberFormatException exception ) {
                System.out.println( "La chaîne ne contient pas d'entier" );
            } catch( Exception exception ) {
                System.out.println( "une exception quelconque" );
            }
            tryMaxCount--;  // On réduit le nombre de tentatives restantes.
        }
        
        if ( tryMaxCount > 0 ) {
            System.out.println( "Value == " + value );
        } else {
            System.out.println( "Mais tu fais quoi ?" );
        }
    }
    
}
On retente le bloc try au maximum trois fois.

Pour finir ces explications sur les blocs catch, notez bien qu'il n'est pas obligatoire de fournir un bloc catch, mais dans ce cas un bloc finally devra obligatoirement être spécifié.

Le mot clé finally.

Vous pouvez ajouter un dernier bloc à votre instruction try / catch : le bloc finally. Ce bloc est facultatif, mais si vous le fournissez, il devra obligatoirement être positionné en dernier. Il permet de dire ce que vous souhaitez faire en fin d'instruction try et ce quelle que soit la manière dont il se termine (en succès ou en échec).

Voici un exemple de code qui permet de fermer deux fichiers après traitement, même si le traitement échoue. Dans notre cas, le traitement sera une copie de fichier.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
 49 
 50 
 51 
 52 
 53 
 54 
 55 
 56 
 57 
 58 
 59 
 60 
 61 
 62 
 63 
 64 
 65 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Copy {
    
    public static void main( String [] args ) {
        
        // Si vous ne fournissez pas deux paramètres au main,
        // on affiche l'usage de notre commande.
        if ( args.length == 0 ) {
            System.out.println( "Usage: java Copy sourceFile destFile" );
            System.exit( 0 );
        }
        
        // On calcule le nombre total d'octets du fichier source.
        long length = new File( args[0] ).length();

        // On prépare trois variables qui correspondent au fichier source,
        // au fichier de destination ainsi qu'un buffer d'octets.
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;
        byte [] buffer = new byte[ 1024 * 1024 ];
        
        try {
        
            // On ouvre les deux fichiers (en lecture et en écriture)
            inputStream = new FileInputStream( args[0] );
            outputStream = new FileOutputStream( args[1] );
        
            // On recopie les octets du fichier, tant qu'il y en a.
            while ( length > 0 ) {
                int readedBytes = inputStream.read( buffer );
                outputStream.write( buffer, 0, readedBytes );
                length -= readedBytes;
            }
        
            System.out.println( "Copie du fichier terminée" );
            
        } catch( IOException exception ) { 
            
            // Il y a donc eu une erreur durant la copie des fichiers
            System.err.println( "Impossible de réaliser la copie du fichier" );
            
        } catch( SecurityException exception ) { 
            
            // On a un problème de droits sur les fichiers (java.lang.SecurityException)
            System.err.println( "Vous n'avez pas les droits pour réaliser la copie du fichier" );
        
        } finally {
            
            // On ferme les fichiers.
            if ( inputStream != null ) {
                try { inputStream.close(); } catch( Exception e ) { /* Tant pis */ }
            }
            if ( outputStream != null ) {
                try { outputStream.close(); } catch( Exception e ) { /* Tant pis */ }
            }
            
        }
        
    }
    
}
Une copie de fichier utilisant un bloc finally
depuis Java SE 7.0, il existe une manière plus propre de coder ce programme en utilisant une instruction « try-with-resources ». Nous y reviendrons dans un prochain chapitre.

Comme nous l'avons dit, nous pouvons aussi avoir une instruction try / finally sans bloc catch. En voici un petit exemple.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
public class Sample {
    
    public static void main( String [] args ) {
        
        try {
            int randomValue = (int) (Math.random() * 3);
            // Attention : cà peut produire une erreur en cas de division par 0
            int res = 1 / randomValue;      
            System.out.println( "Résultat == " + res );
        } finally {
            System.out.println( "On a terminé !" );
        }
    }
    
}
Une instruction try / finally sans bloc catch

Du coup, soit une exception est produite et vous observerez le résultat suivant.

Exception in thread "main" java.lang.ArithmeticException: / by zero
    at Sample.main(Sample.java:8)
On a terminé !

Soit tout se passe bien et vous aurez le résultat suivant.

Résultat == 0
On a terminé !

On relaye l'exception.

Le mot clé throws

Vous n'êtes pas obligé de traiter votre erreur au niveau ou vous êtes. Dans ce cas, il faut indiquer sur la signature de la méthode que vous relayez le traitement de l'exception au niveau de la méthode « appelante ». Cela se fait en utilisant le mot clé throws à la suite de la liste de paramètres de la méthode. Voici un exemple de syntaxe.

 1 
 2 
 3 
public void aMethod() throws IOException {
    // . . .
}
Exemple de définition d'une méthode relayant d'éventuelles exceptions
le langage Java propose bien deux mots clés très proches du point de vue de leurs noms. Le mot clé throw (sans « s » final) permet de déclencher une erreur, alors que le mot clé throws (avec le « s » final) permet de relayer le traitement de l'exception à la méthode appelante.

Passons à un exemple un peu plus concret : on reprend la copie de fichier proposée précédemment, mais notez que cette fois-ci, en cas d'erreur, on botte en touche : la méthode main relaye l'exception au niveau supérieur. Sauf que dans notre cas, le niveau supérieur, c'est la JVM : celle-ci interceptera les éventuelles exceptions et se contentera de les afficher sur la console.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
 48 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Copy {
    
    public static void main( String [] args ) throws IOException {
        
        // Si vous ne fournissez pas deux paramètres au main,
        // on affiche l'usage de notre commande.
        if ( args.length == 0 ) {
            System.out.println( "Usage: java Copy sourceFile destFile" );
            System.exit( 0 );
        }
        
        // On calcule le nombre total d'octets du fichier source.
        long length = new File( args[0] ).length();

        // On prépare trois variables qui correspondent au fichier source,
        // au fichier de destination ainsi qu'un buffer d'octets.
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;
        byte [] buffer = new byte[ 1024 * 1024 ];
        
        try {
            inputStream = new FileInputStream( args[0] );
            outputStream = new FileOutputStream( args[1] );
        
            while ( length > 0 ) {
                int readedBytes = inputStream.read( buffer );
                outputStream.write( buffer, 0, readedBytes );
                length -= readedBytes;
            }
            System.out.println( "Copie du fichier terminée" );
        
        } finally {
            if ( inputStream != null ) {
                try { inputStream.close(); } catch( Exception e ) { /* Tant pis */ }
            }
            if ( outputStream != null ) {
                try { outputStream.close(); } catch( Exception e ) { /* Tant pis */ }
            }
        }
        
    }
    
}
On botte en touche sur la gestion des erreurs

Si vous lancez votre programme en spécifiant un fichier source non existant, vous pourrez obtenir ce type de message d'erreur sur la console.

Exception in thread "main" java.io.FileNotFoundException: aFile.txt (Aucun fichier ou dossier de ce type)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at Copy.main(Copy.java:27)

A savoir, sur une déclaration de méthodes, vous pouvez spécifier plusieurs types d'exceptions pouvant être relayée à la méthode appelante.

 1 
 2 
 3 
public void aMethod() throws IOException, SQLException {
    // . . .
}
Exemple de définition d'une méthode relayant plusieurs types d'exceptions

Vous devez, normalement, dire ce que vous faites de vos exceptions

Il y a, en Java, une règle très importante sur la gestion des exceptions : sauf dans un cas particulier (nous allons y revenir plus loin), vous devez obligatoirement dire ce que vous faites en cas de déclenchement d'exception. Soit vous traitez l'exception, via un bloc try / catch, soit vous relayez le traitement de l'exception à la méthode appelante via le mot clé throws. Si vous dite rien quant au traitement d'une exception, une erreur de compilation sera inexorablement produite. Voici un exemple de code produisant une telle erreur de compilation.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
 41 
 42 
 43 
 44 
 45 
 46 
 47 
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class Copy {
    
    public static void main( String [] args ) {
        
        // Si vous ne fournissez pas deux paramètres au main,
        // on affiche l'usage de notre commande.
        if ( args.length == 0 ) {
            System.out.println( "Usage: java Copy sourceFile destFile" );
            System.exit( 0 );
        }
        
        // On calcule le nombre total d'octets du fichier source.
        long length = new File( args[0] ).length();

        // On prépare trois variables qui correspondent au fichier source,
        // au fichier de destination ainsi qu'un buffer d'octets.
        FileInputStream inputStream = null;
        FileOutputStream outputStream = null;
        byte [] buffer = new byte[ 1024 * 1024 ];
        
        try {
            inputStream = new FileInputStream( args[0] );
            outputStream = new FileOutputStream( args[1] );
        
            while ( length > 0 ) {
                int readedBytes = inputStream.read( buffer );
                outputStream.write( buffer, 0, readedBytes );
                length -= readedBytes;
            }
            System.out.println( "Copie du fichier terminée" );
        
        } finally {
            if ( inputStream != null ) {
                try { inputStream.close(); } catch( Exception e ) { /* Tant pis */ }
            }
            if ( outputStream != null ) {
                try { outputStream.close(); } catch( Exception e ) { /* Tant pis */ }
            }
        }
        
    }
    
}
Un exemple de code n'indiquant pas quoi faire en cas d'erreur : il ne compilera pas !

Et voici les erreurs de compilation produites par ce programme (il y a effectivement plusieurs lignes de codes pouvant déclencher une erreur).

$> javac Copy.java
Copy.java:26: error: unreported exception FileNotFoundException; must be caught or declared to be thrown
            inputStream = new FileInputStream( args[0] );
                          ^
Copy.java:27: error: unreported exception FileNotFoundException; must be caught or declared to be thrown
            outputStream = new FileOutputStream( args[1] );
                           ^
Copy.java:30: error: unreported exception IOException; must be caught or declared to be thrown
                int readedBytes = inputStream.read( buffer );
                                                  ^
Copy.java:31: error: unreported exception IOException; must be caught or declared to be thrown
                outputStream.write( buffer, 0, readedBytes );
                                  ^
4 errors
$> 

Notez aussi que, si vous utiliser un IDE tel qu'Eclipse, ces erreurs vous sont directement signifiées dans l'éditeur de code Java. Voici une capture d'écran montrant ces erreurs.

Exemple de restitution d'erreur sur la gestion d'exception par Eclipse

Les exceptions et la documentation de votre code

Si vous êtes déjà développeur C++ ou C#, vous vous posez peut-être une question. Dans ces langages, il n'est pas obligatoire de dire ce qu'on fait en cas d'erreur. Alors pourquoi, en Java, il est obligatoire de le faire ?

Il y a plusieurs manières que justifier ce choix. Pour moi, la réponse la plus importante est que si vous n'étiez pas conscient qu'un code pouvait planter, le fait d'avoir produit l'erreur de compilation fait que maintenant vous l'êtes. Et du coup, vous produisez des codes forcément plus robustes (sauf si vous bottez en touche avec l'instruction throws, bien entendu).

La deuxième justification importante, de mon point de vue, est que, comme l'utilisation du throws fait partie de la signature de la méthode, quand vous produirez automatiquement ou utilisez des documentations Javadoc, l'information comme quoi telle méthode peut potentiellement produire une erreur vous sera systématiquement proposée (et y compris de manière intégrée à Eclipse). Voici un exemple de documentation Javadoc indiquant qu'une exception peut être déclenchée (méthode java.io.FileInputStream.read( byte [] buffer)).

Exemple de documentation sur une méthode pouvant produire des exceptions

Nous reviendrons sur la manière de produire une documentation au format « Javadoc » dans un prochain chapitre.

On déclenche une exception avec l'instruction throw

Ceux qui ont lu les chapitres précédents de ce cours/tutoriel de programmation Java auront certainement remarqué que nous avons déjà un peu parlé de comment déclencher une exception : effectivement, dans le chapitre de programmation orientée objet consacré à l'encapsulation nous avions vérifié que la valeur passé en dénominateur d'un nombre rationnel (une fraction) soit bien différente de 0. Si ce n'était pas le cas, nous produisions une erreur via le mot clé throw. Pour rappel, voici le code que nous avions proposé pour la méthode setDenominator.

 1 
 2 
 3 
 4 
 5 
 6 
public void setDenominator( int denominator ) {
    if ( denominator == 0 ) {
        throw new RuntimeException( "denominator cannot be zero" );
    }
    this.denominator = denominator;
}
Exemple de déclenchement d'une exception particulière
le langage Java propose bien deux mots clés très proches du point de vue de leurs noms. Le mot clé throw (sans « s » final) permet de déclencher une erreur, alors que le mot clé throws (avec le « s » final) permet de relayer le traitement de l'exception à la méthode appelante.

L'instruction throw permet de déclencher l'instance d'exception passée en argument. Dans notre cas, il s'agit d'une nouvelle instance (utilisation de l'opérateur new), mais vous auriez pu préalablement produire l'instance, puis la déclencher ultérieurement. La syntaxe suivante est tout aussi valide.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
public void setDenominator( int denominator ) {
    if ( denominator == 0 ) {
        RuntimeException exc = new RuntimeException( "denominator cannot be zero" ); 
        throw exc;
    }
    this.denominator = denominator;
}
Exemple de déclenchement d'une exception particulière


Les classes scellées Mise en oeuvre d'une classe d'exception