Подтвердить что ты не робот

Поддерживает ли Java RAII/детерминированное уничтожение?

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

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

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

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

4b9b3361

Ответ 1

EDIT: ответ ниже был написан в начале 2009 года, когда Java 7 был очень популярен.

В то время как Java по-прежнему не имеет детерминированного разрушения, он получил такую ​​функцию, как оператор С# using: оператор try-with-resources.


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

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

Стоит понять, что есть причины, по которым детерминированное разрушение не реализовано в Java и .NET, кстати, оно имеет тенденцию включать подсчет ссылок, который: a) влияет на производительность, а b) терпит неудачу с циклическими ссылками. Брайан Гарри написал подробное электронное письмо об этом - об .NET, и он старше 8 лет, но он хорошо стоит прочитать.

Ответ 2

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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