Чтение онлайн

на главную - закладки

Жанры

Философия Java3

Эккель Брюс

Шрифт:

Некоторые люди утверждают, что статические методы со своей семантикой глобальной функции противоречат объектно-ориентированной парадигме; в случае использования статического метода вы не посылаете сообщение объекту, поскольку отсутствует ссылка this. Возможно, что это справедливый упрек, и если вы обнаружите, что используете слишком много статических методов, то стоит пересмотреть вашу стратегию разработки программ. Однако ключевое слово static полезно на практике, и в некоторых ситуациях они определенно необходимы. Споры же о «чистоте ООП» лучше оставить теоретикам.

Очистка: финализация и сборка мусора

Программисты помнят и знают о важности инициализации, но часто забывают о значимости «приборки». Да и зачем,

например, «прибирать» после использования обычной переменной int? Но при использовании программных библиотек «просто забыть» об объекте после завершения его работы не всегда безопасно. Конечно, в Java существует сборщик мусора, освобождающий память от ненужных объектов. Но представим себе необычную ситуацию. Предположим, что объект выделяет «специальную» память без использования оператора new. Сборщик мусора умеет освобождать память, выделенную new, но ему неизвестно, как следует очищать специфическую память объекта. Для таких ситуаций в Java предусмотрен метод finalize, который вы можете определить в вашем классе. Вот как он должен работать: когда сборщик мусора готов освободить память, использованную вашим объектом, он для начала вызывает метод finali-ze,H только после этого освобождает занимаемую объектом память. Таким образом, метод finalize позволяет выполнять завершающие действия во время работы сборщика мусора.

Все это может создать немало проблем для программистов, особенно для программистов на языке С++, так как они могут спутать метод finalize с деструктором языка С++ — функцией, всегда вызываемой перед разрушением объекта. Но здесь очень важно понять разницу между Java и С++, поскольку в С++ объекты разрушаются всегда (в правильно написанной программе), в то время как в Java объекты удаляются сборщиком мусора не во всех случаях. Другими словами:

ВНИМАНИЕ-:-

1. Ваши объекты могут быть и не переданы сборщику мусора.

2. Сборка мусора не является удалением.

Если программа завершает свою работу и сборщик мусора не удалил ни одного объекта и не освободил занимаемую память, то эта память будет возвращена операционной системе после завершения работы программы. Это хорошо, так как сборка мусора сопровождается весомыми издержками, и если сборщик не используется, то, соответственно, эти издержки не проявляются.

Для чего нужен метод finalize?

Итак, если метод finalize не стоит использовать для проведения стандартных операций завершения, то для чего же он нужен? Запомните третье правило:

ВНИМАНИЕ -

3. Процесс сборки мусора относится только к памяти.

Единственная причина существования сборщика мусора — освобождение памяти, которая перестала использоваться вашей программой. Поэтому все действия, так или иначе связанные со сбором мусора, особенно те, что записаны в методе finalize, должны относиться к управлению и освобождению памяти.

Но значит ли это, что если ваш объект содержит другие объекты, то в finalize они должны явно удаляться? Нет — сборщик мусора займется освобождением памяти и удалением объектов вне зависимости от способа их создания. Получается, что использование метода finalize ограничено особыми случаями, в которых ваш объект размещается в памяти необычным способом, не связанным с прямым созданием экземпляра. Но, если в Java все является объектом, как же тогда такие особые случаи происходят?

Похоже, что поддержка метода finalize была введена в язык, чтобы сделать возможными операции с памятью в стиле С, с привлечением нестандартных механизмов выделения памяти. Это может произойти в основном при использовании методов, предоставляющих способ вызова He– Java-кода из программы на Java. С и С++ пока являются единственными поддерживаемыми языками, но, так как для них таких ограничений нет, в действительности программа Java

может вызвать любую процедуру или функцию на любом языке. Во внешнем коде можно выделить память вызовом функций С, относящихся к семейству malloc. Если не воспользоваться затем функцией free, произойдет «утечка» памяти. Конечно, функция free тоже принадлежит к С и С++, поэтому придется в методе finalize провести вызов еще одного «внешнего» метода.

После прочтения этого абзаца у вас, скорее всего, сложилось мнение, что метод finalize используется нечасто11. И правда, это не то место, где следует проводить рутинные операции очистки. Но где же тогда эти обычные операции будут уместны?

Очистка — ваш долг

Для очистки объекта его пользователю нужно вызвать соответствующий метод в той точке, где эти завершающие действия по откреплению и должны осуществляться. Звучит просто, но немного протйворечит традиционным представлениям о деструкторах С++. В этом языке все объекты должны уничтожаться. Если объект С++ создается локально (то есть в стеке, что невозможно в Java), то удаление и вызов деструктора происходит у закрывающей фигурной скобки, ограничивающей область действия такого объекта. Если же объект создается оператором new (как в Java), то деструктор вызывается при выполнении программистом оператора С++ delete (не имеющего аналога в Java). А когда программист на С++ забывает вызвать оператор delete, деструктор не вызывается и происходит «утечка» памяти, к тому же остальные части объекта не проходят необходимой очистки. Такого рода ошибки очень сложно найти и устранить, и они являются веским доводом в пользу перехода с С++ на Java.

Java не позволяет создавать локальные объекты — все объекты должны быть результатом действия оператора new. Но в Java отсутствует аналог оператора delete, вызываемого для разрушения объекта, так как сборщик мусора и без того выполнит освобождение памяти. Значит, в несколько упрощенном изложении можно утверждать, что деструктор в Java отсутствует из-за присутствия сборщика мусора. Но в процессе чтения книги вы еще не раз убедитесь, что наличие сборщика мусора не устраняет необходимости в деструкторах или их аналогах. (И никогда не стоит вызывать метод finalize непосредственно, так как этот подход не решает проблему.) Если же потребуется провести какие-то завершающие действия, отличные от освобождения памяти, все же придется явно вызвать подходящий метод, выполняющий функцию деструктора С++, но это уже не так удобно, как встроенный деструктор.

Помните, что ни сборка мусора, ни финализация не гарантированы. Если виртуальная машина Java (Java Virtual Machine, JVM) далека от критической точки расходования ресурсов, она не станет тратить время на освобождение памяти с использованием сборки мусора.

Условие «готовности»

В общем, вы не должны полагаться на вызов метода finalize — создавайте отдельные «функции очистки» и вызывайте их явно. Скорее всего, finalize пригодится только в особых ситуациях нестандартного освобождения памяти, с которыми большинство программистов никогда не сталкивается. Тем не менее существует очень интересное применение метода finalize, не зависящее от того, вызывается ли он каждый раз или нет. Это проверка условия готовности12объекта.

В той точке, где объект становится ненужным — там, где он готов к проведению очистки, — этот объект должен находиться в состоянии, когда освобождение закрепленной за ним памяти безопасно. Например, если объект представляет открытый файл, то он должен быть соответствующим образом закрыт, перед тем как его «приберет» сборщик мусора. Если какая-то часть объекта не будет готова к уничтожению, результатом станет ошибка в программе, которую затем очень сложно обнаружить. Ценность finalize в том и состоит, что он позволяет вам обнаружить такие ошибки, даже если и не всегда вызывается. Единожды проведенная финализация явным образом укажет на ошибку, а это все, что вам нужно.

Поделиться:
Популярные книги

Прогрессор поневоле

Распопов Дмитрий Викторович
2. Фараон
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прогрессор поневоле

Господин моих ночей (Дилогия)

Ардова Алиса
Маги Лагора
Любовные романы:
любовно-фантастические романы
6.14
рейтинг книги
Господин моих ночей (Дилогия)

Идеальный мир для Лекаря

Сапфир Олег
1. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря

Авиатор: назад в СССР

Дорин Михаил
1. Авиатор
Фантастика:
попаданцы
альтернативная история
5.25
рейтинг книги
Авиатор: назад в СССР

На границе империй. Том 8. Часть 2

INDIGO
13. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 8. Часть 2

Барон Дубов 4

Карелин Сергей Витальевич
4. Его Дубейшество
Фантастика:
юмористическое фэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Барон Дубов 4

Имперский Курьер. Том 3

Бо Вова
3. Запечатанный мир
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Имперский Курьер. Том 3

Бестужев. Служба Государевой Безопасности. Книга 5

Измайлов Сергей
5. Граф Бестужев
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бестужев. Служба Государевой Безопасности. Книга 5

Адвокат Империи 2

Карелин Сергей Витальевич
2. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 2

Баронесса. Эхо забытой цивилизации

Верескова Дарья
1. Проект «Фронтир Вита»
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Баронесса. Эхо забытой цивилизации

Адвокат Империи 7

Карелин Сергей Витальевич
7. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 7

Чехов

Гоблин (MeXXanik)
1. Адвокат Чехов
Фантастика:
фэнтези
боевая фантастика
альтернативная история
5.00
рейтинг книги
Чехов

Крещение огнем

Сапковский Анджей
5. Ведьмак
Фантастика:
фэнтези
9.40
рейтинг книги
Крещение огнем

Невеста клана

Шах Ольга
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
Невеста клана