Итак, сборщик мусора, он же GC –
Рассмотрим типовой пример, когда сборщик мусора спасает от ошибки программирования, но не спасает от ошибки проектирования. Речь о контейнере, являющемся владельцем своих объектов. Наиболее распространённой ошибкой является сохранение ссылок на эти объекты в другом объекте вне контейнера. При этом часто оказывается, что ссылки ещё живы, но указывают в пустоту, потому что контейнер уже удалён. В случае «ручного» управления в традиционных языках, таких как C++, при обращении по ссылке возникнет ошибка, ведущая к сбою или отказу. При наличии сборщика мусора программа продолжит работу, хотя объекты так и останутся висеть в памяти. Конечно, приятно осознавать, что программа не свалится с ошибкой, а продолжит работу. Особенно если это относительно критичное серверное приложение. Но проблема-то остаётся. Например, «висящие» объекты могут продолжать использовать или даже блокировать системные ресурсы. А могут и просто занимать недопустимо много памяти.
Решение здесь достаточно простое.
НУЖНО ВЗЯТЬ ЗА ПРАВИЛО, ЧТО
контейнер всегда управляет своими объектами. Поэтому обращаться к его внутренним объектам нужно только через интерфейс самого контейнера.
При этом быть готовым к обработке ситуации, когда контейнер говорит: «Извини, но такой объект уже удалён или пока недоступен». Если же объект переходит во владение к другому контейнеру, то он перестаёт управляться прежним. И процесс передачи объекта и управления также не может быть реализован простым присваиванием полученной ссылки.
Метафора из жизни. Вам нужна цитата из книги, библиотечный код которой вы знаете. Пусть цитата занимает одну страницу в книге, её номер вы знаете. Библиотека – контейнер книг. Книжный магазин – тоже. Варианты взаимодействия:
1. Пойти в библиотеку и взять книгу на время. У контейнера остаётся ссылка на вас, если потом книгу будут снимать с учёта (удалять), то о вас вспомнят и попросят вернуть.
//Правильно:
читатель. Книги. Добавить(библиотека. Выдать(код, читатель));
//Ошибка:
читатель. Книги. Добавить(библиотека. Книги(код));Кстати, ошибка в данном примере означает, что книгу, между нами говоря, вы попросту спёрли, а интерфейс библиотеки позволяет это легко сделать.
2. Обратиться в справочную службу библиотеки и попросить их прислать копию нужной страницы.
//Правильно:
читатель. Реферат. Цитаты. Добавить(библиотека. КопироватьСтраницу(код,
номер_страницы));
//Ошибка:
читатель. Реферат. Цитаты. Добавить(библиотека. Книги(код). Страницы(номер_
страницы));3. В библиотеке книги не оказалось, купить книгу в магазине.
//Правильно:
покупатель. Книги. Добавить(магазин. Продать(код, покупатель));
//Ошибка:
покупатель. Книги. Добавить(магазин. Книги(код));