Как работает хранитель финализатора в java?

Как работает «хранитель финализатора» [Effective Java, стр. 30]?

Вы использовали их? Решил ли он какую-то конкретную проблему?


person Vinoth Kumar C M    schedule 29.07.2011    source источник
comment
Не использовал его. Может потому, что я не пишу финализаторы.   -  person duffymo    schedule 29.07.2011


Ответы (1)


Это решает проблему подкласса, забывшего вызвать метод finalize суперкласса. Этот шаблон работает путем присоединения дополнительного экземпляра с переопределенным finalize к вашему суперклассу. Таким образом, если суперкласс выйдет за пределы области действия, присоединенный экземпляр также выйдет из области видимости, что вызовет выполнение его finalize, который, в свою очередь, вызовет finalize окружающего класса.

Вот короткий фрагмент, демонстрирующий паттерн опекуна в действии:

public class Parent {

    public static void main(final String[] args) throws Exception {
        doIt();
        System.gc();
        Thread.sleep(5000); //  5 sec sleep
    }

    @SuppressWarnings("unused")
    private final Object guardian = new Object() {
        @Override protected void finalize() {
            doFinalize();
        }
    };

    private void doFinalize() {
        System.out.println("Finalize of class Parent");
    }

    public static void doIt() {
        Child c = new Child();
        System.out.println(c);
    }

}

class Child extends Parent {

    // Note, Child class does not call super.finalize() but the resources held by the
    // parent class will still get cleaned up, thanks to the guardian pattern
    @Override protected void finalize() {
        System.out.println("Finalize of class Child");
    }

}
person Sanjay T. Sharma    schedule 29.07.2011
comment
Но когда придет время для родительского класса быть GC'ed, родительский класс не сможет быть GC'ed, поскольку анонимный класс содержит ссылку на родительский класс, а родительский класс также содержит ссылку на анонимный класс через ссылка на поле экземпляра. Итак, из-за этой циклической ссылки, как родительский и анонимный класс будут иметь право на сборку мусора? - person Geek; 26.09.2013
comment
@Geek: Java имеет довольно классный GC, который не отключается циклическими ссылками. Подробнее здесь - person Sanjay T. Sharma; 26.09.2013
comment
Должен ли Parent.finalize() позвонить Parent.doFinalize()? Разве это не приводит к тому, что doFinalize() вызывается дважды, если Child действительно вызывает super.finalize() или если завершен экземпляр Parent? - person Michael Anderson; 24.06.2014
comment
@МайклАндерсон: +1; вы действительно правы, упомянув, что открытый класс Parent не должен иметь переопределенный метод finalize. Отредактировано. - person Sanjay T. Sharma; 28.07.2014
comment
@SanjayT.Sharma, Что касается Примечания, класс Child не вызывает super.finalize(), пока в первую очередь, почему это вообще могло произойти? Разве не частью контракта для всех финализаторов дочерних классов является вызов super finalize ? - person Pacerier; 18.09.2017
comment
@Pacerier: Нет, это не часть контракта (просто еще один переопределенный метод) и единственная причина наличия шаблона опекуна. Это не работает как цепочка конструкторов. - person Sanjay T. Sharma; 18.09.2017