2010-06-16 19 views
21

Używam buforowanego programu piszącego i mój kod, zamyka pisarz w bloku finally. Mój kod jest taki.Czy można w końcu użyć funkcji catch catch inside?

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

muszę użyć try catch up wewnątrz czystego kodu w końcu jako theBufferedWriter może również rzucić IOException. Nie chcę odrzucać tego wyjątku do meto wzywającego. Czy jest to dobra praktyka, aby w końcu użyć funkcji catch catch? Jeśli nie, jaka jest alternatywa? Proszę zasugeruj.

Pozdrawiam, Hiral

+1

jest ok, ale aby sprawdzić zerowy najpierw jest lepiej. – qrtt1

+0

+1 To nie jest ładne, ale musi być zrobione –

Odpowiedz

14

nieco ładniejszy sposób to zrobić jest użycie IOUtils.closeQuiety z Apache commons-io. Utrzymuje porządek w twoim kodzie i eliminuje niektóre elementy, które są nieodłączne w Javie.

kod staje się wówczas:

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

wiele ładniejszy i bardziej wyraziste.

+3

Zamknięcie buforowany pisarz taki jak ten jest ryzykowny; jeśli postacie pozostają w buforze, a zamknięcie powoduje wyjątek podczas próby ich zapisu, dane są przycinane, a aplikacja nie obsługuje błędu. Aby było to bezpieczne, musisz wywołać 'close' tuż przed blokiem catch. – McDowell

+2

@McDowell: Dobrze wiedzieć. Prawdopodobnie możesz nazwać 'flush()' przed blokiem catch też, prawda? –

+2

zamknięcie bufora spowoduje jego wyczyszczenie (patrz javadoc). _W przypadku, gdy nie jest to jasne, ten wzorzec wymaga, aby 'close' był wywoływany dwa razy ._ Jeśli przeniesiesz _try/finally {close} _ do istniejącego bloku _try_, to 1) musisz tylko raz wywołać' close' 2) uniknąć zbędnego przypisania "null" 3) nie trzeba importować biblioteki innej firmy. Zagnieżdżone tryby wyglądają brzydko, ale zazwyczaj nie można podejmować decyzji dotyczących obsługi błędów tak lokalnie, tak więc blok catch byłby w wywołującym na stosie wywołań. http://illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html – McDowell

11

W pre Java 7, powiedziałbym tego, co zostało napisane jest najlepszym rozwiązaniem.

W języku Java 7 i nowszych wersjach masz Automatic Resource Management przeznaczone do uproszczenia tych rzeczy. Dzięki tej funkcji można zrobić

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

Zgadzam się spróbować z zasobem jest najlepszym podejściem od Java 7: https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html – JavaDev

1

To jest to, z czym będziemy musieli żyć do momentu wydania Java 7 i ARM Blocks.

2

Możesz też użyć adnotacji Lombok i @Cleanup, a nigdy więcej nie napiszesz wpadki próbnej do środka.

ten sposób normalnie można napisać to (uwaga throws IOException):

//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(); 
    } 
    } 
} 

Teraz z Lombok po prostu napisać @Cleanup na strumieniach

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

Jest OK, ale należy sprawdzić, czy theBufferedWriter nie jest pusty przed zamknięciem.
Można również zrobić:

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

czyli

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(); 
} 

ale przeważnie robię takie operacje (np napisanie pliku) w specjalnej metody i wolą rzucać/wyjątek tak rozmówcy

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 
} 

Uwaga: angielski nie jest moim jodły można go (np prośbą o innym pliku, zatrzymanie aplikacji ...) uchwyt t ani mój drugi język, każda pomoc zostanie doceniona:

0

Jest w porządku, aby umieścić próbny połów w końcu. Jest to narzędzie, które robi to, co chcesz robić. Jednak czuję, że rzucony na siebie wyjątek IOException jest na tyle rzadki, że pozwoliłbym mu tłumić każdy wyjątek w ciele.

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