2I002
FIABILITÉ & EXCEPTIONS
Vincent Guigue & Christophe Marsala
Le cours est inspiré de sources diverses:
L. Denoyer, F Peschanski, E. Chailloux...
Enjeux du cours
Améliorer la fiabilité des programmes développés
Etudions les outils qui vont nous donner confiance dans le code développé...
1
Objectif 1: code compilé = code fonctionnel
Les erreurs de compilation sont les plus faciles à corriger...
Respectons les règles de développement
Utilisons des outils pour provoquer des erreurs de compilation si le code prend mauvaise tournure...
Annotations (aide au compilateur)
2
Objectif 2: en cours d’exécution, détectons les erreurs et informons l’utilisateur Fonctionnement des ruptures (exceptions)
Déclenchement, traitement....
3
Vers la programmation par contrat
Fiabilité = respect des règles de développement
Idée
Pour éviter les erreurs, respecter les règles:
Choix des noms pour comprendre qui fait quoi
Classes & méthodes de taille raisonnable, limiter les accès public Les opérations complexes sont déléguées à d’autres classes Le client voit peu de choses: facile à comprendre, évite les failles
Taille limitée = on peut envisager de relire le code de la classe si nécessaire Evolutivité/architecture réfléchie (pour éviter les modifications ultérieures...), usage de final...
Plus le code est clair, plus les erreurs sont faciles à voir
final ⇒ attributs static = CONSTANTES
Pour sécuriser le code, interdisons les modifications de certaines valeurs (notamment les constantes).
Exemple : Math.PI, sécurisation = impossibilité de modifier Note : une constante est indépendante des instances ⇒ static Usage : une constante est définie en majuscule
1 p u b l i c c l a s s M a C l a s s e {
2 p u b l i c final s t a t i c i n t MACONSTANTE = 1 0 ;
3 . . .
Usage:
Constantes universelles (Color.RED, Color.YELLOW, Math.PI, Double.POSITIVE_INFINITY...)
Typologie (type de codage d’un pixel, organisation du BorderLayout)...
Bornes algorithmiques (NB_ITER_MAX, TAILLE_MAX...)
final ⇒ attributs static = CONSTANTES
Pour sécuriser le code, interdisons les modifications de certaines valeurs (notamment les constantes).
Exemple : Math.PI, sécurisation = impossibilité de modifier Note : une constante est indépendante des instances ⇒ static Usage : une constante est définie en majuscule
1 p u b l i c c l a s s M a C l a s s e {
2 p u b l i c final s t a t i c i n t MACONSTANTE = 1 0 ;
3 . . .
Usage:
Constantes universelles (Color.RED, Color.YELLOW, Math.PI, Double.POSITIVE_INFINITY...)
Typologie (type de codage d’un pixel, organisation du BorderLayout)...
final pour les attributs
Idée : protéger ses objets... Et ses programmes
Initialiser les valeurs des attributs sans pouvoir les modifier ensuite Exemple : String
1 p u b l i c c l a s s P o i n t {
2 p u b l i c final d o u b l e x , y ;
3 p u b l i c P o i n t (d o u b l e x , d o u b l e y ) {
4 t h i s. x = x ; t h i s. y = y ;
5 }
6 // i n t e r d i c t i o n de m o d i f i e r x , y d a n s l a s u i t e
7 // ( e t c h e z l e c l i e n t )
8 }
Interdiction de modifier x et y dans les méthodes
(pas de setter, pas de translation...) Modification d’un Point = création d’une nouvelle instance
Possibilité de laisser les attributs public... Puisque non modifiable
Sécurité lorsqu’un objet est passé en argument de méthode
Exemple sur la voiture 1/2 [public/private]
1 Voiture = 2 visions
Vision client: accès aux contrôles comme un pilote (pédales, volant)
Vision développeur: physique complexe à gérer pour obtenir un comportement réaliste
1
Limiter la vision public:
commandes pédales/volant ⇒ public
calcul de la mise à jour de la position/direction, dérapage éventuel ⇒ private
2
Limiter la taille des méthodes/classes
Gestion de la physique = moteur physique ou géométrie dans l’espace... ⇒ classes
outils, vecteur, fichier gérées à part
Exemple sur la voiture 2/2 [organisation]
Idée
1
Code morcelé = code plus lisible
2
Code morcelé = code testable
Développer plusieurs main pour tester le bon fonctionnement des différentes fonctions basiques
En séparant la gestion de la physique de la voiture, il devient possible de tester chaque fonction du moteur physique...
Plus facile de tester/corriger des méthodes basiques plutôt que l’ensemble d’une méthode très complexe
NB: il s’agit des prémices de la programmation par contrat (cf plus loin & 3i002)
Définition générale de la fiabilité (correction et robustesse) [E. Chailloux]
Spécification et réalisation :
Un développement informatique est la réalisation effective d’une spécification.
Un programme n’a pas d’erreur s’il est conforme à la spécification.
Cette conformité peut être vérifiée par :
une preuve réalisée formellement (automatiquement ou à la main)
testée dynamiquement durant l’exécution en vérifiant les propriétés désirées.
Vérifications statiques
Idée
Faire en sorte de vérifier un maximum de chose au niveau de la compilation... Plus facile à corriger
Par défaut le compilateur vérifie syntaxe (;, parenthèses, accolades...)
type des variables et compatibilité avec les instances et méthodes appelées niveau d’accès (aux méthodes, variables...)
d’autres propriétés sont plus difficiles à montrer et nécessitent plus d’informations transmises au compilateur
langage d’annotations
Annotations standards
@Override : pour indiquer une redéfinition de méthode
@Deprecated : pour indiquer un élément dépprécié, engendre un warning
@SuppressWarnings : pour désactiver ponctuellement des warnings Certaines erreurs ne pose pas de problème de compilation mais provoque des comportements étranges lors de l’exécution... Ce sont les plus chères à corriger!
1 @ O v e r r i d e
2 p u b l i c S t r i n g t o S t r i g ( ) { // => e r r e u r de c o m p i l a t i o n
3 r e t u r n " P o i n t ␣ [ x=" + x + " , ␣ y=" + y + " ] ";
4 }
Erreur du type:
1 P o i n t . j a v a : 2 3 : method d o e s n o t o v e r r i d e o r i m p l e m e n t a method f r o m a s u p e r t y p e
2 @ O v e r r i d e
Langages d’annotations pour Java [E. Chailloux]
Annotations en Java 1.5 : petit langage d’annotations intégré au langage depuis la 1.5
JML (Java Modeling Language) est un langage de spécifications
1 /∗ e n s u r e s \ r e s u l t >= x && \ r e s u l t >= y &&
2 \ f o r a l l i n t e g e r z ;
3 z >= x && z >= y ==> z >= \ r e s u l t ;
4 ∗/
5 p u b l i c s t a t i c i n t max (i n t x , i n t y ) {
6 i f ( x>y ) r e t u r n x ; e l s e r e t u r n x ;
7 }
permet d’être ensuite utilisées par des outils de vérification comme ESC/Java 2 (Extended Static Checker for Java 2)
Krakatoa (Paris-sud 11, Inria)
NB: hors programme pour 2i002...Vérifications dynamiques
Une fois la compilation passée, il reste de nombreuses erreurs possibles...
Les tests ne sont pas finis!
⇒ faire des tests sur les arguments des méthodes pour vérifier la faisabilité
⇒ faire des tests sur les sorties des méthodes pour vérifier la crédibilité des résultats obtenus
Exemples:
Tester si la case demandée dans un tableau existe avant de retourner le résultat Tester si la valeur de retour de la fonction carre est bien positive
Tester si l’argument de la division est bien différent de 0
...
Réaction en cas d’échec du test Que faire?
utiliser une valeur spéciale : null, NaN
1 // d a n s un main
2 d o u b l e r ;
3 r = Math . a s i n ( 2 . 0 ) ;
4 // NB : a s i n n ’ a c c e p t e que d e s v a l e u r s e n t r e −1 e t 1
5 S y s t e m . o u t . p r i n t l n ( r ) ; // NaN
effectuer une rupture de calcul
1 A r r a y L i s t <Double> a r r = new A r r a y L i s t <Double > ( ) ;
2 a r r . add ( 1 . ) ; a r r . add ( 2 . ) ; a r r . add ( 4 . ) ;
3 S y s t e m . o u t . p r i n t l n ( a r r . g e t ( 3 ) ) ;
4
5 // E x c e p t i o n i n t h r e a d " main " j a v a . l a n g . I n d e x O u t O f B o u n d s E x c e p t i o n : I n d e x : 3 , S i z e : 3
6 // a t j a v a . u t i l . A r r a y L i s t . RangeCheck ( A r r a y L i s t . j a v a : 5 4 7 )
7 // a t j a v a . u t i l . A r r a y L i s t . g e t ( A r r a y L i s t . j a v a : 3 2 2 )
8 // a t c o u r s 4 . T e s t . main ( T e s t . j a v a : 1 9 )
⇒ Vous avez observé ces réponses sur d’autres objets...
Valeurs spéciales
Exploitation du null:
1 // c l i e n t
2 P o i n t p = P o i n t . r e c h e r c h e P o s i t i f ( t a b ) ;
3 // s o i t p p o i n t e v e r s une i n s t a n c e
4 // p o s i t i v e . . . s o i t p e s t n u l l
5 i f( p == n u l l) {
6 S y s t e m . o u t . p r i n t l n
7 (" Pas ␣ de ␣ p o i n t ␣ p o s i t i f ") ;
8 }
1 // c l a s s P o i n t
2 p u b l i c s t a t i c P o i n t
3 r e c h e r c h e P o s i t i f ( P o i n t [ ] t ) {
4 f o r( P o i n t p : t )
5 i f( p . x > 0 && p . y > 0 )
6 r e t u r n p ;
7 r e t u r n n u l l;
8 }
Exploitation du Nan:
1 // c l i e n t
2 d o u b l e d = TestNan . m o n C a l c u l ( 2 ) ;
3
4 i f( D o u b l e . isNaN ( d ) )
5 S y s t e m . o u t . p r i n t l n
6 (" C a l c u l ␣ i m p o s s i b l e ") ;
7 e l s e
8 S y s t e m . o u t . p r i n t l n ( d ) ;
1 p u b l i c s t a t i c d o u b l e
2 m o n C a l c u l (d o u b l e a ) {
3 i f( a >0)
4 r e t u r n 2∗Math . s q r t ( a ) −5;
5 r e t u r n D o u b l e . NaN ;
6 }
Valeurs spéciales
Exploitation du null:
1 // c l i e n t
2 P o i n t p = P o i n t . r e c h e r c h e P o s i t i f ( t a b ) ;
3 // s o i t p p o i n t e v e r s une i n s t a n c e
4 // p o s i t i v e . . . s o i t p e s t n u l l
5 i f( p == n u l l) {
6 S y s t e m . o u t . p r i n t l n
7 (" Pas ␣ de ␣ p o i n t ␣ p o s i t i f ") ;
8 }
1 // c l a s s P o i n t
2 p u b l i c s t a t i c P o i n t
3 r e c h e r c h e P o s i t i f ( P o i n t [ ] t ) {
4 f o r( P o i n t p : t )
5 i f( p . x > 0 && p . y > 0 )
6 r e t u r n p ;
7 r e t u r n n u l l;
8 }
Exploitation du Nan:
1 // c l i e n t
2 d o u b l e d = TestNan . m o n C a l c u l ( 2 ) ;
3
4 i f( D o u b l e . isNaN ( d ) )
5 S y s t e m . o u t . p r i n t l n
6 (" C a l c u l ␣ i m p o s s i b l e ") ;
7 e l s e
8 S y s t e m . o u t . p r i n t l n ( d ) ;
1 p u b l i c s t a t i c d o u b l e
2 m o n C a l c u l (d o u b l e a ) {
3 i f( a >0)
4 r e t u r n 2∗Math . s q r t ( a ) −5;
5 r e t u r n D o u b l e . NaN ;
6 }
Valeurs spéciales
Exploitation du null:
1 // c l i e n t
2 P o i n t p = P o i n t . r e c h e r c h e P o s i t i f ( t a b ) ;
3 // s o i t p p o i n t e v e r s une i n s t a n c e
4 // p o s i t i v e . . . s o i t p e s t n u l l
5 i f( p == n u l l) {
6 S y s t e m . o u t . p r i n t l n
7 (" Pas ␣ de ␣ p o i n t ␣ p o s i t i f ") ;
8 }
1 // c l a s s P o i n t
2 p u b l i c s t a t i c P o i n t
3 r e c h e r c h e P o s i t i f ( P o i n t [ ] t ) {
4 f o r( P o i n t p : t )
5 i f( p . x > 0 && p . y > 0 )
6 r e t u r n p ;
7 r e t u r n n u l l;
8 }
Exploitation du Nan:
1 // c l i e n t
2 d o u b l e d = TestNan . m o n C a l c u l ( 2 ) ;
3
4 i f( D o u b l e . isNaN ( d ) )
5 S y s t e m . o u t . p r i n t l n
6 (" C a l c u l ␣ i m p o s s i b l e ") ;
1 p u b l i c s t a t i c d o u b l e
2 m o n C a l c u l (d o u b l e a ) {
3 i f( a >0)
4 r e t u r n 2∗Math . s q r t ( a ) −5;
5 r e t u r n D o u b l e . NaN ;
6 }
Valeurs spéciales
Exploitation du null:
1 // c l i e n t
2 P o i n t p = P o i n t . r e c h e r c h e P o s i t i f ( t a b ) ;
3 // s o i t p p o i n t e v e r s une i n s t a n c e
4 // p o s i t i v e . . . s o i t p e s t n u l l
5 i f( p == n u l l) {
6 S y s t e m . o u t . p r i n t l n
7 (" Pas ␣ de ␣ p o i n t ␣ p o s i t i f ") ;
8 }
1 // c l a s s P o i n t
2 p u b l i c s t a t i c P o i n t
3 r e c h e r c h e P o s i t i f ( P o i n t [ ] t ) {
4 f o r( P o i n t p : t )
5 i f( p . x > 0 && p . y > 0 )
6 r e t u r n p ;
7 r e t u r n n u l l;
8 }
Exploitation du Nan:
1 // c l i e n t
2 d o u b l e d = TestNan . m o n C a l c u l ( 2 ) ;
3
4 i f( D o u b l e . isNaN ( d ) )
5 S y s t e m . o u t . p r i n t l n
6 (" C a l c u l ␣ i m p o s s i b l e ") ;
7 e l s e
8 S y s t e m . o u t . p r i n t l n ( d ) ;
1 p u b l i c s t a t i c d o u b l e
2 m o n C a l c u l (d o u b l e a ) {
3 i f( a >0)
4 r e t u r n 2∗Math . s q r t ( a ) −5;
5 r e t u r n D o u b l e . NaN ;
6 }
Rupture de calcul = Exceptions
Une exception est une rupture de calcul.
Elle est utilisée :
pour éviter les erreurs de calcul division par zéro
accès à la référence null ouverture d’un fichier inexistant . . .
comme style de programmation
En Java une exception est un objet
Création de l’objet plantage
Déclenchement d’un plantage...
... Et récupération de ce plantage!
Rupture de calcul = Exceptions
Une exception est une rupture de calcul.
Elle est utilisée :
pour éviter les erreurs de calcul division par zéro
accès à la référence null ouverture d’un fichier inexistant . . .
comme style de programmation En Java une exception est un objet
Création de l’objet plantage Déclenchement d’un plantage...
... Et récupération de ce plantage!
Exceptions : création et déclenchment
Hiérarchie de classes (détails dans le cours suivant):
1 j a v a . l a n g . O b j e c t
2 e x t e n d e d by j a v a . l a n g . T h r o w a b l e
3 e x t e n d e d by j a v a . l a n g . E x c e p t i o n
4 e x t e n d e d by j a v a . l a n g . R u n t i m e E x c e p t i o n
Création d’une exception (= utilisation d’un objet existant) :
1 R u n t i m e E x c e p t i o n e = new R u n t i m e E x c e p t i o n (" D i v i s i o n ␣ p a r ␣ z e r o ") ;
Déclenchement (throw) :
1 throw e ;
Note: création & Déclenchement sont souvent combinés
1 throw new R u n t i m e E x c e p t i o n (" D i v i s i o n ␣ p a r ␣ z e r o ") ;
Exemple: gestion d’une pile d’entiers Rappel:
Une pile est une structure FILO: First In Last Out.
Le premier objet mis dans la pile sort en dernier.
1 p u b l i c c l a s s P i l e {
2 p r i v a t e i n t[ ] i t e m s ;
3 p r i v a t e i n t n i v e a u ;
4 p u b l i c P i l e ( ) { i t e m s = new i n t[ 1 0 ] ; n i v e a u = 0 ; }
5
6 p u b l i c v o i d e m p i l e r (i n t i t e m ) {
7 i t e m s [ n i v e a u ++] = i t e m ; // s y n t a x e c o m p a c t e
8 }
9
10 p u b l i c i n t d e p i l e r ( ) {
11 r e t u r n i t e m s [−−n i v e a u ] ;
12 }
13 }
Pile : fonctionnement Usage normal :
1 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
2 P i l e p = new P i l e ( ) ;
3 f o r(i n t i =0; i <6; i ++) // m e t t r e 6 e n t i e r s
4 p . e m p i l e r ( i ) ;
5
6 f o r(i n t i =0; i <6; i ++) // e n l e v e r 6 e n t i e r s
7 S y s t e m . o u t . p r i n t l n ( p . d e p i l e r ( ) ) ;
8 // a f f i c h a g e de : 5 4 3 . . . 0
9 }
Erreur d’utilisation:
1 f o r(i n t i =0; i <6; i ++) // m e t t r e 6 e n t i e r s
2 p . e m p i l e r ( i ) ;
3 f o r(i n t i =0; i <7; i ++) // e n l e v e r 7 e n t i e r s
4 S y s t e m . o u t . p r i n t l n ( p . d e p i l e r ( ) ) ;
5 // E x c e p t i o n i n t h r e a d " main " j a v a . l a n g . A r r a y I n d e x O u t O f B o u n d s E x c e p t i o n : −1
6 // a t c o u r s 4 . P i l e . d e p i l e r ( P i l e . j a v a : 1 3 )
Pile : fonctionnement Usage normal :
1 p u b l i c s t a t i c v o i d main ( S t r i n g [ ] a r g s ) {
2 P i l e p = new P i l e ( ) ;
3 f o r(i n t i =0; i <6; i ++) // m e t t r e 6 e n t i e r s
4 p . e m p i l e r ( i ) ;
5
6 f o r(i n t i =0; i <6; i ++) // e n l e v e r 6 e n t i e r s
7 S y s t e m . o u t . p r i n t l n ( p . d e p i l e r ( ) ) ;
8 // a f f i c h a g e de : 5 4 3 . . . 0
9 }
Erreur d’utilisation:
1 f o r(i n t i =0; i <6; i ++) // m e t t r e 6 e n t i e r s
2 p . e m p i l e r ( i ) ;
3 f o r(i n t i =0; i <7; i ++) // e n l e v e r 7 e n t i e r s
4 S y s t e m . o u t . p r i n t l n ( p . d e p i l e r ( ) ) ;
5 // E x c e p t i o n i n t h r e a d " main " j a v a . l a n g . A r r a y I n d e x O u t O f B o u n d s E x c e p t i o n : −1
6 // a t c o u r s 4 . P i l e . d e p i l e r ( P i l e . j a v a : 1 3 )
7 // a t c o u r s 4 . T e s t P i l e . main ( T e s t P i l e . j a v a : 1 4 )
La méthode dépiler a provoqué une rupture de calcul...
Le programme s’est arrêté: les instructions suivantes ne sont pas exécutées Bonne chose !! Si le programme continue avec une exécution faussée, l’erreur est plus dure à déceler
Le message n’est pas clair
⇒ il faut: (1) détecter l’erreur et (2) envoyer un message clair
Pile sécurisée
1 p u b l i c v o i d e m p i l e r (i n t i t e m ) {
2 i f( n i v e a u >=c a p a c i t e )
3 throw new R u n t i m e E x c e p t i o n (" La ␣ p i l e ␣ e s t ␣ p l e i n e :
4 ␣ ␣ i m p o s s i b l e ␣ d ’ a j o u t e r ␣ d e s ␣ e l e m e n t s ") ;
5 i t e m s [ n i v e a u ++] = i t e m ;
6 }
7
8 p u b l i c i n t d e p i l e r ( ) {
9 i f( n i v e a u <=0)
10 throw new R u n t i m e E x c e p t i o n (" La ␣ p i l e ␣ e s t ␣ v i d e :
11 ␣ ␣ i m p o s s i b l e ␣ d ’ e x t r a i r e ␣ d e s ␣ e l e m e n t s ") ;
12 r e t u r n i t e m s [−−n i v e a u ] ;
13 }
En cas de problème à l’exécution :
1 // E x c e p t i o n i n t h r e a d " main " j a v a . l a n g . R u n t i m e E x c e p t i o n :
2 // La p i l e e s t v i d e : i m p o s s i b l e d ’ e x t r a i r e d e s e l e m e n t s
3 // a t c o u r s 4 . P i l e . d e p i l e r ( P i l e . j a v a : 2 1 )
Exceptions : récupération d’exceptions
+ structure try ... catch
1 t r y {
2 . . . i n s t r u c t i o n s . . .
3 }
4 c a t c h (< t y p e e x c e p t i o n > < v a r i a b l e >) {
5 . . . i n s t r u c t i o n s . . .
6 }
7 f i n a l l y {
8 . . . i n s t r u c t i o n s . . .
9 }
La clause finally sera toujours exécutée avant de sortir du bloc try.
Exemple en Java
1 P i l e p = new P i l e ( ) ;
2 f o r(i n t i =0; i <6; i ++)
3 p . e m p i l e r ( i ) ;
4 5 t r y{
6 f o r(i n t i =0; i <8; i ++){
7 S y s t e m . o u t . p r i n t l n ( p . d e p i l e r ( ) ) ; // rupture pour i=7
8 }
9
10 // c e t t e i n s t r u c t i o n ne s e r a p a s e x e c u t e e
11 S y s t e m . o u t . p r i n t l n (" E s t ␣ c e ␣ que ␣ j e ␣ p a s s e ␣ i c i ? ") ;
12 }c a t c h( R u n t i m e E x c e p t i o n e ) { // récupération de la rupture
13 S y s t e m . o u t . p r i n t l n (" I m p o s s i b l e ␣ de ␣ d e p i l e r ␣=>␣ E x c e p t i o n ") ;
14 S y s t e m . o u t . p r i n t l n (" I n t e r c e p . ␣ de ␣ l ’ e r r e u r ␣ e t ␣ p o u r s u i t e ␣ du ␣ pg ") ;
15 }
16
17 // c e t t e i n s t r u c t i o n s e r a e x e c u t e e
18 S y s t e m . o u t . p r i n t l n (" J e ␣ s u i s ␣ p a s s e ␣ i c i ") ;
Instruction finally Définition
Dans ce bloc figure du code qui sera exécuté de toute façon;
1 P i l e p = new P i l e ( ) ;
2 f o r(i n t i =0; i <6; i ++)
3 p . e m p i l e r ( i ) ;
4 5 t r y{
6 // on e s s a i e l i m i t e = 4 e t l i m i t e = 8
7 f o r(i n t i =0; i <limite ; i ++){
8 S y s t e m . o u t . p r i n t l n ( p . d e p i l e r ( ) ) ;
9 }
10 }c a t c h( R u n t i m e E x c e p t i o n e ) {
11 S y s t e m . o u t . p r i n t l n (" I m p o s s i b l e ␣ de ␣ d e p i l e r ␣=>␣ E x c e p t i o n ") ;
12 S y s t e m . o u t . p r i n t l n (" i n t e r c e p t . ␣ de ␣ l ’ e r r e u r ␣ e t ␣ p o u r s u i t e ␣ du ␣ pg ") ;
13 }f i n a l l y{
14 S y s t e m . o u t . p r i n t l n (" t o t o ") ; // t o u j o u r s e x e c u t e
15 }
Usage peu courant: principalement pour la fermeture de fichier/socket
Attention aux portées des variables
Les blocs limitent la portée des variables
Dans le catch, nous n’avons pas accès aux variables déclarées dans le try
1 t r y{
2 i n t i = 7 ;
3 . . .
4 }c a t c h( R u n t i m e E x c e p t i o n e ) {
5 S y s t e m . o u t . p r i n t l n ( i ) ; //
ne compile pas: i n’existe pas!
6 }
7 // Bonne s o l u t i o n :
8 i n t i = 0 ; // d e c l a r a t i o n a v a n t
9 t r y{
10 i = 7 ; // i n i t i a l i s a t i o n i c i
11 . . .
12 }c a t c h( R u n t i m e E x c e p t i o n e ) {
13 S y s t e m . o u t . p r i n t l n ( i ) ; // OK
14 }
Souvent une source de problèmes avec les fichiers (pour les fermer en cas
d’interruption). ⇒ cf prochain cours.
Attention aux portées des variables
Les blocs limitent la portée des variables
Dans le catch, nous n’avons pas accès aux variables déclarées dans le try
1 t r y{
2 i n t i = 7 ;
3 . . .
4 }c a t c h( R u n t i m e E x c e p t i o n e ) {
5 S y s t e m . o u t . p r i n t l n ( i ) ; // ne compile pas: i n’existe pas!
6 }
7 // Bonne s o l u t i o n :
8 i n t i = 0 ; // d e c l a r a t i o n a v a n t
9 t r y{
10 i = 7 ; // i n i t i a l i s a t i o n i c i
11 . . .
12 }c a t c h( R u n t i m e E x c e p t i o n e ) {
13 S y s t e m . o u t . p r i n t l n ( i ) ; // OK
14 }