Я правильно использую Java 7 try-with-resources
Я ожидаю, что буферизованный читатель и считыватель файлов закроется, а ресурсы будут выпущены, если исключение будет выбрано.
public static Object[] fromFile(String filePath) throws FileNotFoundException, IOException
{
try (BufferedReader br = new BufferedReader(new FileReader(filePath)))
{
return read(br);
}
}
Однако существует ли необходимость иметь предложение catch
для успешного закрытия?
EDIT:
По существу, приведенный выше код в 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;
}
Ответы
Ответ 1
Правильно, и нет требования к предложению catch
. Oracle java 7 doc говорит, что ресурс будет закрыт независимо от того, действительно ли было выбрано исключение.
Вы должны использовать предложение catch
, только если вы хотите отреагировать на исключение. Предложение catch
будет выполнено после закрытия ресурса.
Здесь приведен фрагмент учебник Oracle:
В следующем примере читается первая строка из файла. Он использует экземпляр BufferedReader для чтения данных из файла. BufferedReader это ресурс, который должен быть закрыт после завершения программы это:
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.
... Поскольку экземпляр BufferedReader объявлен в try-with-resource, он будет закрыт независимо от того, будет ли оператор try завершается нормально или внезапно (в результате метод BufferedReader.readLine, генерирующий исключение IOException).
ИЗМЕНИТЬ
Относительно нового отредактированного вопроса:
Код в Java 6 выполняет catch
, а затем блок finally
. Это заставляет ресурсы по-прежнему потенциально открываться в блоке catch
.
В синтаксисе Java 7 ресурсы закрываются перед блоком catch
, поэтому ресурсы уже закрыты во время выполнения блока catch
. Это описано в приведенной выше ссылке:
В операторе try-with-resources выполняется любой блок catch или finally после того, как объявленные ресурсы были закрыты.
Ответ 2
В этом конкретном случае ваше использование 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)
) будет закрыт NOT.
Чтобы избежать этой проблемы, вы должны указать каждый ресурс отдельно следующим образом:
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
, все еще закрывается. Вы можете найти более подробную информацию здесь и здесь.