— І знову привіт!

Зараз я розповім тобі ще про одну чудову штуку — 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, щоб задіяти такі потужні механізми. Але я буду рости в цей бік, дякую, Еллі, за такий цікавий урок.