Какие виды ссылок в Java существуют и как ими пользоваться
Что проверяют
Знаете ли вы четыре вида ссылок и понимаете ли, где применяются слабые.
Как отвечать
Сборщик собирает объект, если до него нет сильной ссылки. Помимо обычных есть три специальных вида из java.lang.ref:
- сильная (обычная): пока она есть, объект жив всегда;
- мягкая (
SoftReference): объект держится, пока хватает памяти, и очищается передOutOfMemoryError. Задумана для кэшей, но на практике плохо предсказуема и мешает сборщику, поэтому современные кэши строят иначе; - слабая (
WeakReference): не удерживает объект вовсе, он собирается при первой же сборке, если сильных ссылок нет. Основной инструмент; - фантомная (
PhantomReference): доступа к объекту не даёт, нужна для действий после уничтожения, вместе сReferenceQueue. Пришла на сменуfinalize.
Где это реально применяется: WeakHashMap для кэша, привязанного ко времени жизни ключа; слушатели, которые не должны продлевать жизнь подписчику; в Android слабая ссылка на активность внутри долгоживущего объекта, чтобы не удерживать экран.
Важная оговорка для Android: слабая ссылка на контекст это не решение проблемы, а её маскировка. Правильнее не хранить контекст активности в долгоживущем объекте вовсе, а использовать applicationContext или область жизни компонента.
Про finalize стоит сказать, что он объявлен устаревшим: момент вызова не гарантирован, объект задерживается в памяти на лишний цикл, а исключения оттуда теряются. Вместо него try-with-resources и Cleaner.
Где спотыкаются
Считают слабую ссылку способом починить утечку вместо устранения причины.
Используют мягкие ссылки для кэша, не зная про их непредсказуемость.
Не могут объяснить, зачем нужна фантомная.
Пишут finalize и рассчитывают, что он гарантированно выполнится.