Имеет ли смысл методу закрытия AutoCloseable вызывать исключение? Как с этим справиться?

В C# это считается плохим потренируйтесь создавать исключения в методе Dispose объекта IDisposable.

Напротив, в java метод close из AutoCloseable позволяет генерировать любое исключение и заставляет вызывающую сторону каким-то образом с ним справиться. Но что разумно ожидать от вызывающего абонента, если это произойдет? Это говорит о том, что попытка закрыть ресурс каким-то образом не удалась. Так должен ли пользователь снова пытаться закрыть ресурс, прежде чем продолжить, возможно, с экспоненциальной задержкой?


person George Simms    schedule 20.10.2014    source источник
comment
Попробуйте это stackoverflow. ком/вопросы/4679409/   -  person Adam Siemion    schedule 20.10.2014


Ответы (3)


Похоже, что каждая операция с ресурсами, включая неявный вызов close(), считается частью блока try{}. Даже с технической/синтаксической точки зрения ресурсы упоминаются вне фигурных скобок {}.

Это означает, что если IOException возникнет во время close(), оно будет перехвачено некоторым предложением catch(), связанным с вашей попыткой (или оно будет распространяться вверх).

О причине, по которой могут возникнуть исключения: close() может вызвать flush(), flush() может вызвать write(), а write() может завершиться ошибкой.

person Erwin Smout    schedule 20.10.2014
comment
Если я попробую (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } и br.close() выдает исключение, то я не смогу снова попытаться закрыть ресурс в том месте, где мне нужно обработать исключение. Это как бы говорит о том, что не стоит снова пытаться закрыть ресурс. - person George Simms; 25.10.2014

Дизайн AutoCloseable является результатом проверенных исключений Java. Некоторые реализации просто должны иметь возможность генерировать проверенные исключения, поэтому требуется throws Exception. Однако реализации должны объявлять более конкретные выбрасываемые типы (если есть):

Несмотря на то, что этот метод интерфейса объявлен для выдачи Exception, разработчикам настоятельно рекомендуется объявлять конкретные реализации метода close для выдачи более конкретных исключений или вообще не выдавать исключений, если операция закрытия не может завершиться неудачно.

Вы не должны генерировать исключения, если есть способ избежать этого, но вы не всегда можете этого избежать. Например, при закрытии BufferedOutputStream с невыполненным data буферизованный поток имеет два варианта; игнорирование незаписанных данных и закрытие или запись их в поток, что может привести к возникновению исключений.

person gustafc    schedule 20.10.2014

Поскольку разработчики Java смогли увидеть проблемы, возникающие при обработке исключений очистки в блоках using .NET, прежде чем реализовывать собственную функцию попытки использования ресурсов, они смогли ее улучшить. В .NET автор блока Dispose часто сталкивается с неприятным выбором между проглатыванием любых возникающих исключений, что позволяет вызывающей программе ошибочно полагать, что все в порядке, или предоставлением исключениям просачиваться из Dispose таким образом, чтобы стереть все доказательства. любого предыдущего исключения. К счастью, Java позволяет избежать этой проблемы.

Если блок try-with-resources завершается нормально, и блок close также завершается успешно, то внешний код видит все как обычно. Если в части try возникает исключение, но close выполняется нормально, внешний код увидит исключение try-block. Если try завершается нормально, но close выбрасывает, внешний код увидит исключение close. И если try выбрасывает, но close тоже выбрасывает, то внешний код увидит исключение try, но также сможет получить любое исключение, возникшее в close (и если во время close возникнет несколько вложенных исключений try-with-resources, все выброшенные исключения будут доступны для внешнего кода).

Следовательно, в отличие от дизайна .NET, который часто вынуждает авторов подавлять некоторые потенциально серьезные исключения, выдаваемые Dispose, дизайн Java предпочитает, чтобы close генерировало исключение каждый раз, когда что-то идет не так, что вызывающая сторона не может поверить, что все в порядке.

person supercat    schedule 21.10.2014
comment
В Java они называются Suppressed Exceptions, и у Throwable есть для них средства доступа. См. раздел «Подавленные исключения» в docs.oracle.com/javase/tutorial/. существенные/исключения/ - person SensorSmith; 20.10.2020
comment
@SensorSmith: не стесняйтесь редактировать такие детали, как сноску. Мой опыт работы с Java предшествует попытке использования ресурсов, поэтому я бы предпочел, чтобы такую ​​сноску написал кто-то более квалифицированный, чем я. - person supercat; 20.10.2020