01
déc.
2009
déc.
2009
Java Quiz #30
Java / JEE ›
Java Quiz
|
Tags :
java
Par Olivier Croisier
Ah, cela faisait longtemps que je ne vous avais pas proposé de quiz !
En voici un simple qui devrait vous distraire en ce jour pluvieux.
Quel est le problème avec cette méthode très classique ?
/** * Affiche le fichier texte passé en paramètre. * Les commentaires indiquent les exceptions potentiellement levées */ public void displayFile(String fileName) throws IOException { BufferedReader br = null; try { br = new BufferedReader(new FileReader(fileName)); // FileNotFoundException String line = null; while ((line=br.readLine()) != null) { // IOException System.out.println(line); } } catch (Exception e) { e.printStackTrace(); throw e; } finally { if (br != null) { br.close(); // IOException } } }
Note : j'ai corrigé le problème du "close()
pas dans un bloc finally
" qui distrayait les lecteurs du véritable problème de ce bout de code.
Réponse :
Ce code ne compile pas à cause du type de l'exception relancée depuis le bloc "catch
".
En effet, la signature de la méthode signale une possible IOException
, alors que nous lançons une Exception
, plus générique, depuis le bloc "catch
".
Nous avons donc deux solutions pour corriger cette erreur :
- Modifier la signature de la méthode pour qu'elle déclare une Exception ; mais ce serait évidemment peu satisfaisant, car il faut toujours manipuler les exceptions les plus précises possibles.
- Modifier le bloc catch pour captuter une simple
IOException
, ou, encore mieux, uneFileNotFoundException
et uneIOException
, afin de réagir finement en cas de problème.
En tout cas, félicitations à tous les lecteurs qui ont rapidement résolu ce quiz !
Commentaires
Ca envoit n'importe quelles exception alors qu'on ne sont déclarées que l'envoi de IOException.
De plus, le bufferreader n'est pas fermé en cas d'erreur de lecture.
...throws IOException {
...catch (Exception e) {
... throw e;
Il me semble aussi que ça peut boucler à l’infini avec un fichier qui ne se termine pas par un caractère de terminaison (en tout cas c’est le cas avec le flux System.in).
Dans le cas nominal, la méthode close est encore appelée deux fois sur br.
Cela dit, le problème est que e est type comme étant une "Exception", alors que la clause throws de la méthode displayFile ne déclare que des IOException.
Hé, hé... L'initialisation de "line" à "null" est inutile. Comment ça, ça n'est pas un problème ?!? Bon OK... moi je dis : c'est l'exception qui confirme la règle ! ;-)
@HollyDays : il me semble que l'init à null est obligatoire, sous peine de ne pas compiler à la ligne 17.
Je rejoins #1, #2 et #4 sur l'exception. Le code jette potentiellement une exception de type Exception à la ligne 15, qui n'est ni catchée ni déclarée.
A la ligne 18, le code bien écrit devrait plutôt être :
if (br != null) {
}
Le fait que le close se soit mal passé ne devrait pas nécessairement interrompre le fonctionnement normal de l'application.
@Piwaï
Très bonne remarque, je plussois.
On reporte une exception de type Exception alors que seules les exceptions de type IOException sont déclarées dans la signature de la méthode. Ca ne passe pas à la compil.
@ Piwaï
En effet, la variable "br" doit effectivement être initialisé à "null" sous peine de ne pas compiler. Mais ma remarque ne portait pas sur cette variable-là : elle concernait la variable "line". Qui, je le confirme, n'a pas besoin d'être initialisée à "null" ici (vous pouvez vérifier avec le compilateur).
Sinon, pour ceux qui l'ont comprise, mon allusion («c'est l'exception qui confirme la règle ! ;-)») faisait effectivement référence (sic) à l'exception jetée par cette fonction.
Ca ne gène personne que le FileReader qui est un flux ne soit jamais fermé.
Je retire ... le buffredReader s'en occupe quand on le close.
Le probleme est au niveau du throw
catch (Exception e) {
}
La definition de la methode ne permet de ne lever que des exceptions de Type IOException, il faudrait juste changer la signature de la methode par
public void displayFile(String fileName) throws Exception
@HollyDays Ok pour la variable "line" :-)
@regis
Je suppose que c'est une blague :-) . Changer la signature de la méthode, c'est se tirer une balle... J'espère que personne ne développe comme ça ;-) . Mieux vaut modifier ligne 13, Exception en IOException ;-) .
@Piwaï : Oui, il vaut toujours mieux utiliser les exceptions les plus précises. Le must serait même de capturer séparément FileNotFoundException et IOException - mais comme leur traitement est commun ici, en attendant les multi-catch de Java7, on se satisfera de la capture de IOException.