Java7 попробуй с ресурсами Преимущество оператора
Я искал новую функцию Java7. Я нашел один из них - " Попробуй с ресурсами". Кто-нибудь может сказать мне, что именно это означает? Почему и где мы должны его использовать и где мы можем воспользоваться этой функцией? Даже try
заявление пропускает catch
блок который смущает меня.
7 ответов
Он был введен из-за того, что некоторые ресурсы, используемые в Java (такие как соединения или потоки SQL), трудно обрабатывать должным образом; В качестве примера, в Java 6 для правильной обработки InputStream вы должны были сделать что-то вроде:
InputStream stream = new MyInputStream(...);
try {
// ... use stream
} catch(IOException e) {
// handle exception
} finally {
try {
if(stream != null) {
stream.close();
}
} catch(IOException e) {
// handle yet another possible exception
}
}
Вы замечаете эту уродливую двойную попытку? теперь с помощью try-with-resources вы можете сделать это:
try (InputStream stream = new MyInputStream(...)){
// ... use stream
} catch(IOException e) {
// handle exception
}
и close() вызывается автоматически, если он генерирует IOException, он будет подавлен (как указано в спецификации языка Java 14.20.3). То же самое происходит для java.sql.Connection
Оператор try-with-resources является оператором try, который объявляет один или несколько ресурсов. Ресурс - это объект, который должен быть закрыт после завершения программы. Оператор try-with-resources обеспечивает закрытие каждого ресурса в конце оператора. Любой объект, который реализует
java.lang.AutoCloseable
, который включает в себя все объекты, которые реализуютjava.io.Closeable
, может быть использован в качестве ресурса.Следующий пример читает первую строку из файла. Он использует экземпляр BufferedReader для чтения данных из файла. BufferedReader - это ресурс, который должен быть закрыт после завершения работы программы:
static String readFirstLineFromFile(String path) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } }
В этом примере ресурс, объявленный в операторе try-with-resources, является BufferedReader. Оператор объявления появляется в скобках сразу после ключевого слова try. Класс BufferedReader в Java SE 7 и более поздних версиях реализует интерфейс java.lang.AutoCloseable. Поскольку экземпляр BufferedReader объявлен в операторе try-with-resource, он будет закрыт независимо от того, завершается ли оператор try нормально или внезапно
Вы можете прочитать больше здесь.
Обновление с 2017 года после выхода Java 9
Теперь с Java 9
у нас есть больше синтаксического сахара, и мы можем иметь ресурс, объявленный за пределами try-catch
блок, но все еще обрабатывается правильно.
Давайте возьмем для примера это Java 6
Способ обращения с ресурсом:
InputStream stream = new MyInputStream(...);
try {
// ... use stream
} catch(IOException e) {
// handle exception
} finally {
try {
if(stream != null) {
stream.close();
}
} catch(IOException e) {
// handle yet another possible exception
}
}
Здесь мы можем заметить, что этот код невероятно уродлив, как указано в других ответах.
Таким образом, решение в Java 7
должен был представить это try-catch-with-resource
:
try (InputStream stream = new MyInputStream(...)){
// ... use stream
} catch(IOException e) {
// handle exception
}
Эта запись, безусловно, лучше, чем предыдущая, однако у нас есть проблема. Если ресурс (в данном случаеstrem) был объявлен ранее, но мы хотим быть уверены, что он правильно обрабатывается в этом блоке, нам нужен такой прием:
InputStream stream = new MyInputStream(...)
try (InputStream stream2 = stream) {
// do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
// handle exception
}
Мы можем заметить, что эта ситуация может быть решена только с помощью другой части кода. Вот почему в Java 9 был улучшен Try-With-Resources с введением нового синтаксиса:
InputStream stream = new MyInputStream(...)
try (stream) {
// do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
// handle exception
}
Обратите внимание, что этот синтаксис приведет к ошибке времени компиляции для Java версии 8 или минорной
Это более "естественный" способ записи, хотя в большинстве случаев нам не нужен ресурс, выходящий за рамки блока try. Единственное ограничение заключается в том, что переменная читателя должна быть окончательной или только конечной.
В Java, если вы используете такой ресурс, как потоки ввода или вывода, вы всегда должны закрывать его после использования. Он также может генерировать исключения, поэтому он должен быть в try
catch
блок. Закрытие должно быть в finally
блок. Это как минимум путь до Java 7. У этого есть несколько недостатков:
- Вы должны проверить, если ваш ресурс
null
перед закрытием - Само закрытие может генерировать исключения, поэтому ваш
finally
должен был содержать другойtry
-catch
- Программисты, как правило, забывают закрыть свои ресурсы
В то время как первые два являются главным образом проблемами синтаксиса, последний является более критическим. Поэтому, если вы воспользуетесь оператором try-with, ваш код станет намного чище, а главное: ваш ресурс всегда будет закрыт:-)
Преимущество в том, что вам не нужно явно закрывать ресурсы, которые вы определили в инструкции try-with-resources. JVM позаботится об этом. Он автоматически закроет эти ресурсы для вас.
Обычно проблемы, с которыми сталкиваются разработчики, - это структурирование блоков try-catch-finally, потому что даже в блоке finally, где мы закрываем ресурсы, мы должны использовать try-catch. Существуют различные структуры оператора try-catch-finally, чтобы помочь решить эту проблему, но оператор try-with-resources в основном поможет вам упростить логику структуры кода.
Преимущества использования Try с ресурсами
Более читаемый код и легко писать.
Автоматическое управление ресурсами.
Количество строк кода сокращено.
Нет необходимости окончательно блокировать только для того, чтобы закрыть ресурсы.
Мы можем открыть несколько ресурсов в инструкции try-with-resources через точку с запятой. Например, мы можем написать следующий код.
Когда несколько ресурсов открываются в режиме try-with-resources, он закрывает их в обратном порядке, чтобы избежать проблем с зависимостями. Вы можете расширить мою программу ресурсов, чтобы доказать это.
public void sampleTryWithResource() {
try(Connection dbCon = DriverManager.getConnection("url", "user", "password");
BufferedReader br = new BufferedReader(new FileReader("C://readfile/input.txt"));) {
//...Your Business logic
} catch (Exception e) {
//...Exception Handling
}
}
Как насчет этого - если ресурс инициализируется внутри try{}, он автоматически не закрывается?
try {
Scanner scanner = new Scanner(new File(csvFile));
while (scanner.hasNext()) {
// do something
}
scanner.close();
}catch(FileNotFoundException fnfe)
{
System.err.println(fnfe.getLocalizedMessage());
}