2010-01-19 8 views
2

Tout en apprenant Java je tombe sur cette erreur assez souvent. Cela se passe comme suit:Java exception non signalée

Exception non signalée java.io.FileNotFound exception; doit être attrapé ou déclaré être jeté.

java.io.FileNotFound est juste un exemple, j'en ai vu beaucoup de différents. Dans ce cas particulier, le code provoquant l'erreur est:

OutputStream out = new BufferedOutputStream(new FileOutputStream(new File("myfile.pdf"))); 

erreur disparaît toujours et le code compile & fonctionne une fois que je mets avec succès l'instruction à l'intérieur bloc try/catch. Parfois c'est assez bon pour moi, mais parfois non. D'abord, les exemples que j'apprends n'utilisent pas toujours try/catch et devraient fonctionner néanmoins, apparemment.

Ce qui est plus important, parfois quand je mets tout le code à l'intérieur de l'essai/attraper, il ne peut pas fonctionner du tout. Par exemple. dans ce cas particulier, j'ai besoin de out.close(); dans enfin {} bloc; mais si la déclaration ci-dessus elle-même est à l'intérieur du essayez {, enfin { ne voit pas sur et ne peut donc pas le fermer.

Ma première idée était de import java.io.FileNotFound; ou une autre exception pertinente, mais cela n'a pas aidé.

+0

Quelques infos sur le site Web de Sun: [Exceptions] (http://java.sun.com/docs/books/jls/second_edition/html/exceptions.doc. html) – garyj

Répondre

5

Ce dont vous parlez sont checked exceptions, ce qui signifie qu'ils doivent être déclarés ou traités. La construction standard pour traiter des fichiers dans Java ressemble à ceci:

InputStream in = null; 
try { 
    in = new InputStream(...); 
    // do stuff 
} catch (IOException e) { 
    // do whatever 
} finally { 
    if (in != null) { 
    try { 
     in.close(); 
    } catch (Exception e) { 
    } 
    } 
} 

Est-il moche? Sûr. Est-ce verbeux? Sûr. Java 7 le rendra un peu meilleur avec les blocs ARM mais jusque là vous êtes bloqué avec ce qui précède.

Vous pouvez également laisser l'appelant gérer les exceptions:

public void doStuff() throws IOException { 
    InputStream in = new InputStream(...); 
    // do stuff 
    in.close(); 
} 

bien que même alors, le close() devrait probablement être englobés dans un bloc finally.

Mais la déclaration de fonction ci-dessus indique que cette méthode peut lancer un IOException. Comme il s'agit d'une exception vérifiée, l'appelant de cette fonction devra le déclarer (ou le déclarer afin que son appelant puisse le traiter, etc.).

+0

"Handled" Je suppose que signifie essayer/attraper. Et qu'est-ce qui est "déclaré" dans ce cas? – Sejanus

+0

Déclaré signifie ajouté à la signature de méthode dans une clause "throws". –

+0

Got it now, thanks – Sejanus

1

Les exceptions vérifiées de Java font que les programmeurs résolvent les problèmes de ce type. (C'est une bonne chose à mon avis, même si les bogues de balayage sous le tapis est plus facile.)

Vous devriez prendre une mesure appropriée si une panne se produit. Généralement, le traitement doit se faire à une couche différente de celle où l'exception a été lancée.

ressources doivent être traitées comme il faut, qui prend la forme:

acquire(); 
try { 
    use(); 
} finally { 
    release(); 
} 

Ne placez jamais le acquire() dans le bloc try. Ne jamais rien mettre entre les acquire() et try (autre qu'un simple assign). N'essayez pas de libérer plusieurs ressources dans un seul bloc finally.

Donc, nous avons deux problèmes différents. Malheureusement, la syntaxe Java mélange les deux. La bonne façon d'écrire un tel code est:

try { 
    final FileOutputStream rawOut = new FileOutputStream(file); 
    try { 
     OutputStream out = new BufferedOutputStream(rawOut); 
     ... 
     out.flush(); 
    } finally { 
     rawOut.close(); 
    } 
} catch (FileNotFoundException exc) { 
    ...do something not being able to create file... 
} catch (IOException exc) { 
    ...handle create file but borked - oops... 
} 
+0

Merci, j'apprécie toujours les bons conseils de codage. – Sejanus

+0

Pourquoi ne pas mettre acquérir dans le bloc try? –

+0

@BrianGordon Si vous placez l'acquisition dans 'try', vous lancerez la partie release (' finally') même si l'acquisition échoue, ce qui est faux./Maintenant, vous pouvez essayer un code pour vérifier si l'acquisition a réussi et seulement ensuite exécuter la version. Cependant, l'expérience suggère que cela est généralement mal écrit (et clairement non testé), donc vous pouvez aussi bien opter pour un code plus simple. –