Можно ли избежать такой громоздкой попытки ... поймать блок - PullRequest
18 голосов
/ 22 июля 2010

Обычно, когда я имею дело с кодом ввода / вывода Java, вот что я написал

    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) {
            }
        }
    }

Как видите, пока я пытаюсь закрыть поток файлов, мне нужно разобраться с другим блоком try ... catch.

Выглядит хлопотно: (

Есть ли способ, которым я могу избежать? Мне неудобно помещать код закрытия в блок non-finally, так как исключение, вызванное другими кодами, не даст шансов для вызова метода close.

Ответы [ 7 ]

13 голосов
/ 22 июля 2010

Очень важно, чтобы вы наконец закрыли потоки.Вы можете упростить этот процесс с помощью служебного метода, такого как:

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

Я считаю, что по крайней мере необходимо регистрировать ошибку закрытия потока.Тогда использование становится следующим:

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

В Java 7 я считаю, что потоки будут закрываться автоматически, и потребность в таких блоках должна быть в основном избыточной.

6 голосов
/ 22 июля 2010

Автоматическое управление ресурсами поставляется в Java 7, которая автоматически обеспечит обработку этого. До этого такие объекты, как OutputStream, InputStream и другие, реализуют интерфейс Closeable начиная с Java 5. Я предлагаю вам предоставить служебный метод для их безопасного закрытия. Эти методы обычно используют исключения, поэтому убедитесь, что вы используете их только тогда, когда хотите игнорировать исключения (например, в методе finally). Например:

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

Обратите внимание, что метод close() можно вызывать несколько раз, если он уже закрыт, последующие вызовы не будут иметь никакого эффекта, поэтому также предоставьте вызов для закрытия во время нормальной работы блока try, где исключение не будет проигнорировано , Из документации Closeable.close :

Если поток уже закрыт, то вызов этого метода не имеет никакого эффекта

Так что закройте выходной поток в обычном потоке кода, и метод safeClose выполнит закрытие, только если в блоке try произошел сбой:

FileOutputStream out = null;
try {
    out = new FileOutputStream("myfile.txt");
    //... 
    out.close();
    out = null;
} finally {
    IOUtils.safeClose(out);
}
4 голосов
/ 22 июля 2010

Обсуждение на

Try-catch-finally и затем снова попытка catch

и

Есть ли предпочтение для вложенных блоков try / catch?

В принципе, вопрос в том, стоит ли ловить исключение close().

3 голосов
/ 22 июля 2010

Project Lombok предоставляет аннотацию @Cleanup, которая устраняет необходимость использования блоков try catch. Вот пример .

1 голос
/ 22 июля 2010

Напишите метод, который выглядит примерно так: звонок из вашего наконец блока ...

static void wrappedClose(OutputStream os) {
  if (os != null) {
    try {
      os.close();
    }
    catch (IOException ex) {
       // perhaps log something here?
    }
  }
1 голос
/ 22 июля 2010

Я склонен использовать для этого служебные функции:

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

, который изменяет код на более приятный на вкус:

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

Вы не можете добиться большего успеха в Java, по крайней мере, до Java 7, когда (надеюсь) ARM ("Автоматическое управление ресурсами") поможет в некоторой степени.

0 голосов
/ 22 июля 2010

Разделите ваши блоки try / catch и try / finally.

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

Внешний улов также поймает все, что было брошено закрытием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...