Я ожидаю, что буферизованный читатель и читатель файлов закроются, а ресурсы будут освобождены, если исключение выбрано.
public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException
{
try (BufferedReader br = new BufferedReader(new FileReader(filePath)))
{
return read(br);
}
}
Однако существует ли требование catch
об успешном закрытии?
РЕДАКТИРОВАТЬ:
По сути, приведенный выше код в Java 7 эквивалентен приведенному ниже для Java 6:
public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException
{
BufferedReader br = null;
try
{
br = new BufferedReader(new FileReader(filePath));
return read(br);
}
catch (Exception ex)
{
throw ex;
}
finally
{
try
{
if (br != null) br.close();
}
catch(Exception ex)
{
}
}
return null;
}
java-7
try-with-resources
Гепард
источник
источник
catch
вашего примера для Java 6. Т.е.catch (Exception ex) { throw ex; }
- это просто повторное выбрасывание исключения, ничего не делает, его можно легко удалить, не повредив. Или я что-то упускаю?Ответы:
Это правильно, и здесь нет требований к
catch
пункту. В Oracle java 7 doc говорится, что ресурс будет закрыт независимо от того, действительно ли создано исключение.Вы должны использовать
catch
предложение, только если хотите отреагировать на исключение. Предложениеcatch
будет выполнено после закрытия ресурса.Вот отрывок из учебника Oracle :
static String readFirstLineFromFile(String path) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } } // In this example, the resource declared in the try-with-resources statement is a BufferedReader.
РЕДАКТИРОВАТЬ
По поводу нового отредактированного вопроса:
Код в Java 6 выполняет блок,
catch
а затемfinally
блок. Это приводит к тому, что ресурсы все еще могут быть потенциально открыты вcatch
блоке.В Java 7 синтаксиса, ресурсы закрыты , прежде чем в
catch
блоке, поэтому ресурсы уже закрыты во времяcatch
выполнения блока. Это описано в приведенной выше ссылке:источник
В этом конкретном случае использование вами try-with-resources будет работать нормально, но в целом это не совсем правильно. Вы не должны связывать такие ресурсы в цепочку, потому что это может привести к неприятным сюрпризам. Предположим, у вас есть переменный размер буфера:
public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException { int sz = /* get buffer size somehow */ try (BufferedReader br = new BufferedReader(new FileReader(filePath), sz)) { return read(br); } }
Предположим, что что-то пошло не так, и вы
sz
получили отрицательный результат. В этом случае ваш файловый ресурс (созданный черезnew FileReader(filePath)
) НЕ будет закрыт.Чтобы избежать этой проблемы, вы должны указывать каждый ресурс отдельно следующим образом:
public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException { int sz = /* get buffer size somehow */ try (FileReader file = new FileReader(filePath); BufferedReader br = new BufferedReader(file, sz)) { return read(br); } }
В этом случае, даже если инициализация
br
не удалась,file
все равно закрывается. Вы можете найти более подробную информацию здесь и здесь .источник
new FileReader(filePath))
, не закрывается, если создаетсяIllegalArgumentException
отрицательное sz. Не закрывает ли try-with-resources всеAutoClosable
ресурсы независимо от каких-либо исключений?.close()
те переменные, которые были объявлены в инициализаторе try-with-resources. Вот почему разделение его на два объявления в этом примере помогает.sz < 0
конструктор генерирует исключение, на самом деле вызывает утечку ресурса.