Поддерживает ли Java RAII / детерминированное уничтожение? - PullRequest
35 голосов
/ 25 января 2009

Прошло не менее 5 лет с тех пор, как я работал с Java, и тогда каждый раз, когда вы хотели выделить объект, который нужно очистить (например, сокеты, дескрипторы БД), вы должны были не забыть добавить блок finally и вызвать там метод очистки.

Напротив, в C ++ (или других языках, где время жизни объекта является детерминированным, например, Perl), разработчик класса определил бы функцию деструктора, которая выполняет очистку всякий раз, когда объект этого класса выходит из области видимости. Преимущество этого подхода состоит в том, что пользователь объекта не может забыть очистить его - деструктор вызывается автоматически, даже если выдается исключение. Этот подход называется довольно ужасным названием RAII - «Приобретение ресурсов - инициализация».

По моему опыту, выполнение действий «по пути RAII» избавило меня от многих накладных расходов, так как мне не нужно было беспокоиться о том, когда и когда произойдет освобождение ресурсов. Мы рассматриваем возможность использования Java для проекта среднего размера, и мне интересно, входит ли какое-то детерминированное разрушение в число многих новых функций, добавленных в язык с тех пор, как я в последний раз смотрел его. (Я надеюсь, что моя жалоба на то, что «Java не имеет RAII» была осуждена в этой теме , но до сих пор я не смог найти какие-либо подробности путем поиска в Google.)

Так что, если бы кто-то мог указать мне какой-нибудь вводный материал о том, как это сделать на Java, это было бы здорово!

Ответы [ 4 ]

25 голосов
/ 25 января 2009

РЕДАКТИРОВАТЬ: Ответ ниже был написан в начале 2009 года, когда Java 7 была все еще в движении.

Хотя Java все еще не дает гарантий относительно времени завершения, она получила такую ​​функцию, как оператор C # using: оператор try-with-resources .


Нет, Java в этом отношении не изменилась. Вам все еще нужно использовать try / finally.

Обсуждается добавление эквивалента оператора C # "using" (который является синтаксическим сахаром по сравнению с try / finally) в Java, но я не думаю, что это будет частью Java 7 больше. (Кажется, большинство языковых улучшений упало.)

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

9 голосов
/ 14 февраля 2009

Здесь есть шаблон, который помогает. Это не так хорошо, как RAII на основе деструктора, но это означает, что очистка ресурса может быть перенесена в библиотеку (поэтому вы не можете забыть вызвать ее).

Это называется Execute Around и обсуждалось здесь ранее .

Интересно, я вижу, что Джон Скит вмешивался в эту тему, но он не упомянул об этом здесь - как вам не стыдно, Джон - упустил возможность получить несколько очков репутации там!

Кстати, хотя я рад, что Брайан Гарри (снова см. Комментарий Джона) подробно описал письмо, которое он написал, - и это, очевидно, отразило много мыслей, которые ушли в этот процесс - и я рад, что мы получили «использование» этого в C # - я не согласен со всеми его выводами. В частности, я не понимаю, почему, если мы можем использовать использование, у нас не может быть способа пометить тип как ведущий себя таким образом без «использования». Конечно, это ограничивает использование - но также и использование - и в большинстве случаев это именно то, что вы хотите. Проблема с «использованием» заключается в том, что клиентский код все еще должен помнить, чтобы использовать его. В C ++ стиле RAII это свойство типа. Возможно, более серьезная проблема с «использованием», или, точнее, с идиомой Dispose, состоит в том, что это намного сложнее и подвержено ошибкам, чем большинство людей понимают, чтобы получить права - в основном из-за потенциальной возможности возвращения объектов из мертвых.

2 голосов
/ 25 января 2009

Неа. Нет средств для размещения объектов в стеке. Каждый объект расположен в куче и может пережить любой блок, в котором он был инициализирован. Или он может быть собран в середине блока, в зависимости от капризов всего могущественного сборщика мусора.

Если вы работаете на сервере, вы можете проверить Java EE . Он не имеет ничего общего с RAII, но у него есть достойная система для управления жизненными циклами дорогих объектов, таких как соединения с БД. Java EE 5 на самом деле довольно приятен для работы с множеством проблем.

0 голосов
/ 25 января 2009

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

Есть много библиотек, которые делают это. В большинстве случаев вам не о чем беспокоиться.

...