2010-07-22 20 views
18

Zazwyczaj, gdy mamy do czynienia z kodem Java IO, oto co napisałemmogę uniknąć takich kłopotliwych try ... catch bloku

FileOutputStream out = null; 
    try 
    { 
     out = new FileOutputStream("myfile.txt"); 
     // More and more code goes here... 
    } 
    catch (Exception e) 
    { 
    } 
    finally 
    { 
     // I put the close code in finally block, to enture the opened 
     // file stream is always closed even there is exception happened. 
     if (out != null) { 
      // Another try catch block, troublesome. 
      try { 
       out.close(); 
      } catch (IOException ex) { 
      } 
     } 
    } 

Jak widać, podczas gdy próbuję zamknąć strumienia pliku, I potrzebuję poradzić sobie z innym spróbuj ... catch catch.

Spójrz kłopotliwe :(

Czy jest jakiś sposób mogę uniknąć? Nie czuję się komfortowo w oddanie ścisły kod w niewyspecjalizowanych wreszcie zablokować, jako wyjątek spowodowany przez inne kody uczyni żadnej szansy na „zamknij "miano.

+1

Ktoś gdzieś z tobą zgadza się: http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000011.html - ARM Blocks w JDK7. --JA – andersoj

+0

Oh. Czy Joshua Bloch :) –

Odpowiedz

13

Bardzo ważne jest, aby zamknąć strumienie w końcu. Możesz uprościć ten proces za pomocą metody użytkowej, takiej jak:

public static void closeStream(Closeable closeable) { 
    if(null != closeable) { 
     try { 
     closeable.close(); 
     } catch(IOException ex) { 
     LOG.warning("Failed to properly close closeable.", ex); 
     } 
    } 
    } 

Ustanawiam punkt co najmniej logowania awarii bliskiego strumienia. Wykorzystanie wówczas postać:

FileOutputStream out = null; 
try 
{ 
    out = new FileOutputStream("myfile.txt"); 
    // More and more code goes here... 
} 
catch (Exception e) 
{ 
} 
finally 
{ 
    closeStream(out); 
} 

W Javie 7 wierzę, że strumienie będą zamknięte automatycznie, a zapotrzebowanie na takie bloki powinny być przede wszystkim zbędne.

+0

Z tego, co słyszę na SO, Java 7 będzie również spać w mokrym patchu. – kibibu

+0

Czy chodziło Ci o "catch (IOException e)" zamiast "catch (Exception e)"? – janm

+0

To odcięcie oryginalnej kopii przykładowego kodu od użytkownika zadającego pytanie. Ale tak, to powinien być wyjątek IOException. – S73417H

1

staram się wykorzystywać funkcje ułatwiające to:

public static void safeClose(OutputStream out) { 
    try { 
    out.close(); 
    } catch (Exception e) { 
    // do nothing 
    } 
} 

który zmienia kod do nieco bardziej smaczna:

FileOutputStream out = null; 
try { 
    out = new FileOutputStream("myfile.txt"); 
    // do stuff 
} catch (Exception e) { 
    // do something 
} finally { 
    safeClose(out); 
} 

Naprawdę nie można zrobić o wiele lepiej w Javie co najmniej do Java 7, gdy (miejmy nadzieję) ARM ("Automatic Resource Management") blocks pomoże nieco.

+0

Blok ARM? Czy mogę wiedzieć, co to jest? –

+0

Niektóre wskazują na safeClose. Powinieneś również sprawdzić wskaźnik zerowy, prawda? –

+0

@Yah dodał link o blokach ARM do postu. Jeśli chodzi o sprawdzanie 'null', możesz, ale w dużej mierze jest to zbyteczne. Jeśli rzucisz 'NullPointerException', to i tak zostanie on przechwycony w klauzuli catch. Ale oczywiście możesz dodać ten czek, jeśli chcesz. – cletus

6

Automatic Resource Management pojawi się w Javie 7, który automatycznie zapewni obsługę tego. Do tego czasu obiekty takie jak OutputStream, InputStream i inne implementują interfejs Closeable od wersji Java 5. Proponuję podać metodę narzędzia do bezpiecznego zamknięcia tych. Te metody na ogół wykorzystują wyjątki, więc upewnij się, że używasz ich tylko wtedy, gdy chcesz ignorować wyjątki (np. W metodzie finally). Na przykład:

public class IOUtils { 
    public static void safeClose(Closeable c) { 
     try { 
      if (c != null) 
       c.close(); 
     } catch (IOException e) { 
     } 
    } 
} 

Należy zauważyć, że metoda close() można nazwać kilka razy, jeśli jest już zamknięte kolejne wywołania będzie miała żadnego wpływu, więc również wezwanie, aby zamknąć podczas normalnej eksploatacji bloku try gdzie wyjątek nie zostanie zignorowany.From the Closeable.close documentation:

Jeśli strumień jest już zamknięta, a następnie wywoływanie tej metody nie ma wpływu

Więc zamknij strumień wyjściowy w regularny przepływ kodu oraz metody safeClose będą wykonywać tylko blisko, jeśli coś nie powiodło się w bloku try:

FileOutputStream out = null; 
try { 
    out = new FileOutputStream("myfile.txt"); 
    //... 
    out.close(); 
    out = null; 
} finally { 
    IOUtils.safeClose(out); 
} 
1

Napisz metodę, która wygląda jak poniżej; zadzwonić ze swojego bloku finally ...

static void wrappedClose(OutputStream os) { 
    if (os != null) { 
    try { 
     os.close(); 
    } 
    catch (IOException ex) { 
     // perhaps log something here? 
    } 
    } 
0

Oddziel swoje try/catch i try/finally blocks.

try 
{ 
    FileOutputStream out = new FileOutputStream("myfile.txt"); 
    try 
    { 
     // More and more code goes here... 
    } 
    finally 
    { 
     out.close(); 
    } 
} 
catch (Exception e) 
{ 
    //handle all exceptions 
} 

Zewnętrzny zaczep złapie również wszystko, co zostanie rzucone przy zamknięciu.

+0

Im więcej kodu wstawi się do bloku prób, tym trudniej będzie obsłużyć wyjątki we właściwy sposób. – Darron

+0

Jedynym kodem dodanym do bloku try jest out.close(). Twierdzę, że błąd generowany przez to prawdopodobnie musi być traktowany tak samo jak każdy błąd spowodowany przez tworzenie lub używanie. – ILMTitan

Powiązane problemy