— И снова здравствуйте!

Сейчас я расскажу тебе еще про одну замечательную штуку — WeakReference – слабые ссылки.

Выглядит она почти так же, как и SoftReference:

Пример
//создание объекта Cat
Cat cat = new Cat();

//создание слабой ссылки на объект Cat
WeakReference<Cat> catRef = new WeakReference<Cat>(cat);

//теперь на объект ссылается только слабая ссылка catRef.
cat = null; 

//теперь на объект ссылается еще и обычная переменная cat
cat = catRef.get();

//очищаем слабую ссылку
catRef.clear();

У слабой ссылки есть другая особенность.

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

— А можно еще раз, в чем отличия между этими ссылками?

— Объект, который удерживает от смерти только SoftReference может пережить сколько угодно сборок мусора и скорее всего, будет уничтожен при нехватке программе памяти.

Объект, который удерживает от смерти только WeakReference не переживает ближайшей сборки мусора. Но пока она не произошла, его можно получить, вызвав метод get() у WeakReference и вызвать его методы или сделать что-нибудь еще.

— А если на объект ссылаются и SoftReference и WeakReference?

— Тут все просто. Если на объект есть хотя бы одна обычная ссылка – он считается живым. Такие ссылки, кстати, называются StrongReference.

Если на объект нет обычных ссылок, но есть SoftReference, то он – SoftReference.

Если на объект нет обычных ссылок и SoftReference, но есть WeakReference, то он – WeakReference.

Подумай сам, SoftReference защищает объект от удаления и гарантирует, что объект будет удален только при нехватке памяти. WeakReference удерживает объект до ближайшей сборки мусора. SoftReference удерживает от удаления сильнее.

— Ага. Вроде понятно.

— Отлично, тогда расскажу тебе про еще одну занимательную штуку с использованием WeakReference – это WeakHashMap.

— Звучит серьезно!

— А то! WeakHashMap – это HashMap, у которого ключи – это слабые ссылки – WeakReference.

Т.е. ты добавляешь в такой HashMap объекты и работаешь с ними. Все как обычно.

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

Но, представь, что во всем приложении больше не осталось ссылок на эти объекты. Все что удерживает их от смерти – это несколько WeakReference внутри WeakHashMap. Тогда после ближайшей очистки мусора такие объекты исчезнут из WeakHashMap. Сами. Как будто их там и не было.

— Не уверен, что понял.

— Ты хранишь в WeakHashMap пары объектов – ключ и значение. Но WeakHashMap ссылается на ключи не прямо, а через WeakReference. Поэтому, когда объекты, используемые в качестве ключей, станут слабодостижимыми, они уничтожатся при ближайшей сборке мусора. А значит, из WeakHashMap автоматически удалятся и их значения.

В WeakHashMap очень удобно хранить дополнительную информацию к каким-то объектам.

Во-первых, ее очень легко получить, если использовать сам объект в качестве ключа.

Во-вторых, если объект будет уничтожен, из HashMap исчезнет и он, и все привязанные к нему данные.

Пример:

Пример
//создаем объект для хранения дополнительной информации о пользователе
WeakHashMap<User, StatisticInfo> userStatistics = new WeakHashMap<User, StatisticInfo>();

//кладем информацию о пользователе в userStatistics
User user = session.getUser();
userStatistics.put(user, new StatisticInfo (…));

//получаем информацию о пользователе из userStatistics
User user = session.getUser();
StatisticInfo statistics = userStatistics.get(user);

//удаление любой информации о пользователе из userStatistics
User user = session.getUser();
userStatistics.remove(user);
  1. Внутри WeakHashMap ключи хранятся в виде WeakReference.
  2. Как только объект user будет уничтожен сборщиком мусора, в WeakHashMap неявно вызовется метод remove(user) и любая «привязанная» к объекту user информация, будет удалена из WeakHashMap автоматически.

— Выглядит как мощный инструмент. А где можно его использовать?

— По обстоятельствам. Ну, допустим, у тебя в программе есть нить, которая отслеживает работу некоторых объектов-заданий и пишет информацию о них в лог. Тогда эта нить может хранить отслеживаемые объекты в таком WeakHashMap. Как только объекты станут не нужны, сборщик мусора удалит их, автоматически удалятся и ссылки на них из WeakHashMap.

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