java попробуйте наконец заблокировать, чтобы закрыть поток - PullRequest
30 голосов
/ 29 августа 2011

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

Вот код:

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


}

Ответы [ 8 ]

35 голосов
/ 29 августа 2011

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

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();
}           
24 голосов
/ 29 августа 2011

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

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

Предварительно 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();
}

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

23 голосов
/ 29 августа 2011

В 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, будет автоматически вызываться close() при выходе из блока try.

Это называется Попробуйте с оператором ресурсов .

8 голосов
/ 29 августа 2011

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

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

5 голосов
/ 29 августа 2011

Как и в ответе на библиотеку ввода-вывода Commons, 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;
  }
}

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

2 голосов
/ 29 августа 2011

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

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

Спасибо ...

0 голосов
/ 21 февраля 2019

Первое, что я заметил в вашем коде, это отсутствие фигурных скобок {} в вашем коде, если вы посмотрите на него.также вам нужно инициализировать значение от r до null, поэтому вам нужно сначала передать нулевое значение объекту, чтобы, если записанное вами условие могло выполнить not null проверку состояния и позволить вам закрыть поток.

0 голосов
/ 29 марта 2013
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;
}

источник .Этот образец был полезен для меня.

...