2011-08-28 4 views
27

Я хочу закрыть мой поток в блоке finally, но он бросает IOException, поэтому мне кажется, что мне нужно вложить еще один блок try в мой блок finally, чтобы закрыть поток. Это правильный способ сделать это? Это кажется немного неуклюжим.java try finally block to close stream

Вот код:

public void read() { 
    try { 
     r = new BufferedReader(new InputStreamReader(address.openStream())); 
     String inLine; 
     while ((inLine = r.readLine()) != null) { 
      System.out.println(inLine); 
     } 
    } catch (IOException readException) { 
     readException.printStackTrace(); 
    } finally { 
     try { 
      if (r!=null) r.close(); 
     } catch (Exception e){ 
      e.printStackTrace(); 
     } 
    } 


} 
+0

Возможный дубликат [Есть ли предпочтения для вложенных блоков try/catch?] (Http://stackoverflow.com/questions/183499/is-there-a-preference-for-nested-try-catch-blocks) –

ответ

19

Кажется немного неуклюжим.

Это. По крайней мере, java7 пытается с исправлениями ресурсов.

Pre java7 вы можете сделать closeStream функцию, которая глотает его:

public void closeStream(Closeable s){ 
    try{ 
     if(s!=null)s.close(); 
    }catch(IOException e){ 
     //Log or rethrow as unchecked (like RuntimException) ;) 
    } 
} 

Или поставить попробовать ... наконец-то внутри попытке поймать:

try{ 
    BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream())); 
    try{ 

     String inLine; 
     while ((inLine = r.readLine()) != null) { 
      System.out.println(inLine); 
     } 
    }finally{ 
     r.close(); 
    } 
}catch(IOException e){ 
    e.printStackTrace(); 
} 

Это более многословным и исключение наконец, спрячет его в попытке, но он семантически ближе к try-with-resources, представленному на Java 7.

+0

Я пошел со вторым подходом, так как он стал более чистым и читаемым. Это действительно важно, поскольку мы хотим избежать утечек памяти. – Akshay

8

Да, это неуклюжее, уродливое и запутанной. Одним из возможных решений является использование Commons IO, который предлагает метод closeQuietly.

В колонке «Родственные» в правой части этой страницы есть несколько вопросов, которые на самом деле дублируются, я советую просмотреть их для некоторых других способов решения этой проблемы.

2

Ваш подход в конце концов верный. Если код, который вы вызываете в блоке finally, может вызвать исключение, убедитесь, что вы либо обрабатываете его, либо регистрируете его. Никогда не позволяйте ему пузыриться из блока finally.

В блоке catch вы проглатываете исключение - это неверно.

Благодаря ...

32

Кроме того, если вы используете Java 7, вы можете использовать try-with-resources statement:

try(BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream()))) { 
    String inLine; 
    while ((inLine = r.readLine()) != null) { 
     System.out.println(inLine); 
    } 
} catch(IOException readException) { 
    readException.printStackTrace(); 
}   
20

В Java 7 вы можете сделать это ...

try (BufferedReader r = new BufferedReader(...)){ 
    String inLine; 
    while ((inLine = r.readLine()) != null) { 
      System.out.println(inLine); 
    } 
} catch(IOException e) { 
    //handle exception 
} 
  • Объявление переменной в блоке try требует, чтобы она реализовала AutoCloseable.
  • Объявление переменной в блоке try также ограничивает ее область применения блоком try .
  • Любая переменная, объявленная в блоке try, будет автоматически вызывать close() при выходе из блока try.

Это называется Try with resources statement.

5

Как и в случае с упоминанием библиотеки Commons IO, Google Guava Libraries имеет аналогичный вспомогательный метод для вещей, которые являются java.io.Closeable. Класс com.google.common.io.Closeables.Функция, которую вы ищете, также называется Commons IO: closeQuietly().

Или вы можете свернуть свой собственный, чтобы закрыть кучу вроде этого: Closeables.close (closeable1, closeable2, closeable3, ...):

import java.io.Closeable; 
import java.util.HashMap; 
import java.util.Map; 

public class Closeables { 
    public Map<Closeable, Exception> close(Closeable... closeables) { 

    HashMap<Closeable, Exception> exceptions = null; 

    for (Closeable closeable : closeables) { 
    try { 
     if(closeable != null) closeable.close(); 
    } catch (Exception e) { 
     if (exceptions == null) { 
      exceptions = new HashMap<Closeable, Exception>(); 
     } 
     exceptions.put(closeable, e); 
     } 
    } 

    return exceptions; 
    } 
} 

И даже возвращает карту каких-либо исключений, которые были брошенным или нулевым, если таковые не были.

+0

Кому-то, кто проголосовал за мой ответ, не могли бы вы объяснить, почему я могу учиться у него? –

+0

Я подниму вас, чтобы он уравновешивался. Гува - отличная библиотека – thaspius

0
public void enumerateBar() throws SQLException { 
    Statement statement = null; 
    ResultSet resultSet = null; 
    Connection connection = getConnection(); 
    try { 
     statement = connection.createStatement(); 
     resultSet = statement.executeQuery("SELECT * FROM Bar"); 
     // Use resultSet 
    } 
    finally { 
     try { 
      if (resultSet != null) 
       resultSet.close(); 
     } 
     finally { 
      try { 
       if (statement != null) 
        statement.close(); 
      } 
      finally { 
       connection.close(); 
      } 
     } 
    } 
} 

private Connection getConnection() { 
    return null; 
} 

source. Этот образец был полезен для меня.

+0

спасибо. обновлено. –

Смежные вопросы