Ответ
В Java/Android есть 4 типа ссылок:
- Strong – обычная ссылка, объект не будет собран GC, пока есть strong-ссылка.
- Soft – объект удаляется, когда JVM не хватает памяти. Полезно для кешей.
SoftReference<Bitmap> softRef = new SoftReference<>(bitmap);
- Weak – объект удаляется при следующем проходе GC, даже если память не заполнена. Используется для Listeners, чтобы избежать утечек.
WeakReference<Activity> weakRef = new WeakReference<>(activity);
- Phantom – похожа на Weak, но
get()всегда возвращаетnull. Используется для финализации (например, освобождение native-ресурсов).
Важно: Weak/SoftReference не гарантируют, что объект будет жить дольше, чем strong-ссылки на него.
Ответ 18+ 🔞
А, ну вот, классика, ёпта! Сидишь такой, пишешь код, думаешь — всё под контролем. А потом бац — утечка памяти, и приложение твоё накрылось медным тазом. И начинаешь искать, кто виноват. А виноваты зачастую вот эти самые ссылки, про которые все вроде слышали, но как применять — хуй с горы.
Смотри, в Java, а значит и в Android, ссылки — это не просто "объект на объект". Это, блядь, целая философия управления памятью, если разобраться. Их четыре вида, и каждый — для своих, ебать, граблей.
Первый, Strong — это наш обычный дед, MyClass obj = new MyClass();. Пока хоть одна такая ссылка на объект есть, сборщик мусора (GC) на него даже не посмотрит косо. Он неприкосновенный, как священная корова. Удалил все strong-ссылки — только тогда объект становится кандидатом на вылет в трубу.
Дальше идёт Soft. Вот это хитрая жопа! Объект, на который ссылается SoftReference, живёт до последнего. Пока память есть — он тут. Но как только JVM понимает, что "ой, всё, щас будет OutOfMemoryError", она начинает эти мягкие ссылки прибирать. Идеально, ёпта, для кеша картинок! Сделал, положил в мягкую ссылку, и не паришься. Есть память — картинка загружена, нет памяти — система её сама потихоньку подчистит, и пользователь даже не заметит, кроме лёгкого тормоза при повторной загрузке.
SoftReference<Bitmap> softRef = new SoftReference<>(bitmap);
Третий тип — Weak. Вот тут уже построже. Слабак, блядь. Как только на объект не осталось сильных (Strong) ссылок, он сразу в зоне риска. Следующий проход GC — и его нет, даже если память ещё есть. Зачем такое счастье? А чтобы, например, слушателей (Listeners) не забывать отписывать! Сделал WeakReference на Activity, и если активити закрылась и на неё больше никто не ссылается strongly, то и weak-ссылка не помешает GC её похоронить. Красота, утечек нет! Доверия к таким ссылкам, правда, ебать ноль — в любой момент объект может испариться.
WeakReference<Activity> weakRef = new WeakReference<>(activity);
Ну и самый загадочный — Phantom. Фантом, призрак, ёперный театр. Он вроде как Weak, но ещё более бесполезный на первый взгляд. Его метод get() всегда возвращает null! Зачем он тогда нужен, спрашивается? А нужен он для чёткой, контролируемой финализации. Когда тебе надо точно знать, что объект уже мёртв и готов к сборке, но перед этим нужно, например, освободить какие-то нативные (native) ресурсы, которые он держал. Слабая ссылка не даёт такой гарантии — объект может быть уже мёртв, но ещё не собран. А фантомная — да. Сложная тема, для особых случаев.
И главное, что все тут должны понять, иначе будет вам хиросима: WeakReference и SoftReference — это не волшебная таблетка от утечек! Они не продлят жизнь объекту, если на него где-то в другом месте висит обычная, сильная ссылка. Если ты забыл Listener в каком-то списке, который живёт вечно, то хоть обвешай его weak-ссылками — него не соберут. Они работают только тогда, когда сильных ссылок не осталось. Так что, чувак, э бошка думай, где и что ты хранишь.