2010-06-16 14 views
21

Ich verwende einen gepufferten Schreiber und meinen Code, schließt den Schreiber im finally Block. Mein Code ist so.Ist es in Ordnung, versuchen Sie schließlich versuchen, innen zu fangen?

........... 
    BufferedWriter theBufferedWriter = null; 
    try{ 
    theBufferedWriter =..... 
    .... 
    ...... 
    ..... 
    } catch (IOException anException) { 
    .... 
    } finally { 
     try { 
      theBufferedWriter.close();    
     } catch (IOException anException) { 
      anException.printStackTrace(); 
      } 
    } 

Ich habe den Versuch fangen innerhalb des Rein up-Code in schließlich zu verwenden, wie theBufferedWriter auch eine IOException werfen könnte. Ich möchte diese Ausnahme nicht auf die aufrufenden Methoden anwenden. Ist es eine gute Übung, endlich einen Versuch zu machen? Wenn nicht, was ist die Alternative? Bitte vorschlagen.

Grüße, Hiral

+1

es ist in Ordnung, aber zuerst Null zu überprüfen ist besser. – qrtt1

+0

+1 Es ist nicht schön, aber es muss getan werden –

Antwort

14

eine etwas schönere Art und Weise zu tun, dies zu tun IOUtils.closeQuiety von Apache commons-io zu verwenden ist. Es hält Ihren Code sauber und beseitigt einige der in Java enthaltenen Standardwerte.

Sie Code wird dann:

BufferedWriter theBufferedWriter = null; 
try{ 
    theBufferedWriter = ... 
    ... 
} catch (IOException anException) { 
    ... 
} finally { 
    IOUtils.closeQuietly(theBufferedWriter); 
} 

Viel schöner und ausdrucksvoller.

+3

Schließen eines gepufferter Schriftsteller ist riskant; Wenn Zeichen im Puffer verbleiben und beim Versuch, sie zu schließen, eine Ausnahme auslöst, werden die Daten abgeschnitten und Ihre Anwendung verarbeitet den Fehler nicht. Um dies sicher zu machen, müssen Sie kurz vor dem Catch-Block 'close' aufrufen. – McDowell

+2

@ McDowell: Gut zu wissen. Vermutlich könnte man 'flush()' auch vor dem Catch-Block aufrufen, oder? –

+2

Schließen des Puffers wird es leeren (siehe Javadoc). _Wenn es nicht klar ist, erfordert dieses Muster, dass 'close' zweimal aufgerufen wird. _ Wenn Sie _try/finally {close} _ in den vorhandenen _try_Block verschoben haben, müssen Sie 1) nur einmal' close' aufrufen 2) vermeiden Sie die redundante 'Null'-Zuweisung 3) müssen Sie keine 3rd-Party-Bibliothek importieren. Verschachtelte Trys sehen hässlich aus, aber Sie können normalerweise keine Entscheidungen über die Fehlerbehandlung treffen, die dies ohnehin lokal behandelt, so dass der catch-Block in einem Aufrufer weiter oben im Aufruf-Stack sein würde. http://illegalargumenttexception.blogspot.com/2008/10/java-how-not-to-make-of-stream.html – McDowell

11

In Pre Java 7, würde ich sagen, was Sie haben, ist die beste Lösung geschrieben.

In Java 7 und höher haben Sie Automatic Resource Management beabsichtigt, diese Dinge zu vereinfachen. Mit dieser Funktion können Sie

BufferedWriter theBufferedWriter = null; 
try (BufferedWriter theBufferedWriter = ...) { 
.... 
...... 
..... 
} catch (IOException anException) { 
.... 
} 
+0

Ich stimme zu versuchen mit Ressource ist der beste Ansatz seit Java 7: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html – JavaDev

2

Oder Sie können Lombok und die @Cleanup Annotation verwenden und Sie sollten nie wieder einen Versuch fangen innen endlich wieder schreiben.

Dies ist, wie Sie es normalerweise (der Hinweis throws IOException) schreiben würde:

//Vanilly Java 

import java.io.*; 

public class CleanupExample { 
    public static void main(String[] args) throws IOException { 
    InputStream in = new FileInputStream(args[0]); 
    try { 
     OutputStream out = new FileOutputStream(args[1]); 
     try { 
     byte[] b = new byte[10000]; 
     while (true) { 
      int r = in.read(b); 
      if (r == -1) break; 
      out.write(b, 0, r); 
     } 
     } finally { 
     out.close(); 
     } 
    } finally { 
     in.close(); 
    } 
    } 
} 

Jetzt mit Lombok Sie schreiben @Cleanup nur auf den Strömen

import lombok.Cleanup; 
import java.io.*; 

public class CleanupExample { 
    public static void main(String[] args) throws IOException { 
    @Cleanup InputStream in = new FileInputStream(args[0]); 
    @Cleanup OutputStream out = new FileOutputStream(args[1]); 
    byte[] b = new byte[10000]; 
    while (true) { 
     int r = in.read(b); 
     if (r == -1) break; 
     out.write(b, 0, r); 
    } 
    } 
} 
1

Es ist in Ordnung, aber Sie sollten prüfen, ob theBufferedWriter ist nicht null, bevor es geschlossen wird.
Sie könnten auch tun:

BufferedWriter theBufferedWriter; 
try { 
    theBufferedWriter = new ... 
    try { 
     ... 
    } finally { 
     try { 
      theBufferedWriter.close(); 
     } catch (IOException closeException) { 
      closeException.printStackTrace(); 
     } 
    } 
} catch (IOException anException) { 
    ... 
} 

oder:

BufferedWriter theBufferedWriter; 
try { 
    theBufferedWriter = new ... 
} catch (IOException createException) { 
    // do something with createException 
    return; // assuming we are in a method returning void 
} 

try { 
    ... 
} catch (IOException anException) { 
    ... 
    // assuming we don't return here 
} 

try { 
    theBufferedWriter.close(); 
} catch (IOException closeException) { 
    closeException.printStackTrace(); 
} 

aber meistens habe ich solche Operationen in einem speziellen Verfahren (zB eine Datei zu schreiben) und es vorziehen, die/eine Ausnahme so den Anrufer zu werfen damit umgehen kann (zB für eine andere Datei zu fragen, um die Anwendung zu stoppen, ...):

void someMethod(...) throws IOException { 
    BufferedWriter theBufferedWriter = new ... 

    try { 
     ... 
    } catch (IOExcepption anException) { 
     try { 
      theBufferedWriter.close(); 
     } catch (IOException closeException) { 
      closeException.printStackTrace(); 
      // closeException is not thrown, anException represents the main/first problem 
     } 
     throw anException; 
    } 

    theBufferedWriter.close(); // throws the Exception, if any 
} 

Bitte beachten sie: Englisch ist nicht meine Tannen t noch meine zweite Sprache, würde jede Hilfe geschätzt werden

0

Es ist in Ordnung, einen try-catch in einem schließlich zu setzen. Es ist das Werkzeug, das tut, was Sie tun möchten. Ich denke jedoch, dass die ausgelöste IOException beim Schließen ungewöhnlich genug ist, um eine Ausnahme im Körper so zu unterdrücken.

try { 
    BufferedWriter writer = ..... 
    try { 
     ..... 
    } finally { 
     writer.close(); 
    } 
} catch (IOException e) { 
    .... 
} 
Verwandte Themen