Как заменить устаревший метод finalize() из проекта Java 11 взаимозависимостями между классами

У меня есть проект Java 11, включающий несколько классов. В данном сценарии 2 моих класса — A и B — реализуют метод java finalize(), который теперь устарел навсегда. Я понимаю, что этот метод может быть удален в ближайшем будущем, но я думаю, что лучше сразу найти замену финализации.

finalize() в классе A в основном сосредоточен на уничтожении объекта длинного типа, который является защищенной переменной-членом, и на выводе определенных сообщений в журнал. finalize() в классе B просто печатает определенные сообщения в журнал.

Экземпляры класса A создаются из нескольких других классов, а класс B расширяет другой класс ClassLoader. (Фрагменты кода включены ниже.)

Я рассмотрел довольно много предложений, таких как,

Во-первых, они объясняются не так хорошо, и даже когда они объясняются, примеры относятся к проектам одного класса с основным методом, присутствующим в том же классе. Я не могу двигаться вперед с минимальным решением, которое я нашел в Интернете.

Опубликуйте мое исследование. Autocloseable с использованием try-with-resources кажется моим лучшим вариантом. Я понимаю, что мои классы A и B должны реализовывать Autocloseable, в то время как вызываемые (здесь немного не уверен) должны использовать попытку с ресурсами.

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

А.ява

class A
{
    protected long a_var;
    protected A(String stmt, boolean isd)
    {
        // a_var is initialized here
    }

    public void finalize()
    {
        if(a_var != 0)
        {
            log("CALL destroy !");
            destroy(a_var);
            log("DONE destroy !");
        }
    }
}

Б.ява

public class B extends extends ClassLoader
{
    protected void finalize ()
    {
        log("No action");
    }
}

person userAsh    schedule 18.09.2019    source источник
comment
Ну B.finalize() уже ничего не делает, кроме самого лога, и вы вряд ли пропустите посторонние сообщения лога: и он уже недействителен, так как должен вызывать super.finalize() в своем (отсутствующем) finally блоке; так что вы можете просто удалить его со 100% невозмутимостью. Но если C.finalize() существует, то теперь он будет вызываться для экземпляров B, что может оказаться интересным. A.finalize() звонит A.destroy(), которого вы не указали, поэтому комментировать дальше невозможно.   -  person user207421    schedule 18.09.2019
comment
На ум приходит WeakReference (или, возможно, SoftReference). Если объекты находятся в объектно-реляционном сопоставлении, это можно сделать в контейнере (JPA).   -  person Joop Eggen    schedule 18.09.2019
comment
Спасибо, пользователь 207421. Обратите внимание, что класс B расширяет ClassLoader. Я внес необходимые изменения в описание моего запроса выше. Допустим, мне нужно сохранить всю функциональность, которая в настоящее время является частью методов финализации, как мне сделать следующий шаг?   -  person userAsh    schedule 18.09.2019
comment
B расширенный класс C в исходном вопросе, согласно моему комментарию. Но поскольку java.lang.ClassLoader не реализует finalize(), вам вообще не нужно беспокоиться об удалении B.finalize(), как я уже говорил.   -  person user207421    schedule 18.09.2019
comment
Если я удалю B.finalize(), не потеряется ли сообщение журнала? Хотя сообщение, которое я предоставил в вопросе, «Нет действий», это не совсем так в проекте, и необходимо, чтобы я сохранил его. Я что-то упустил здесь?   -  person userAsh    schedule 18.09.2019
comment
Да я это уже говорил. и я также уже сказал, что вы не должны его пропустить, так как он регистрируется когда-то давно, а может быть, и никогда. Необходимо, чтобы вы сохранили его, почему?   -  person user207421    schedule 18.09.2019
comment
java.lang.ref.Cleaner (или лежащая в его основе технология PhantomReference) — это еще один способ заменить finalize() и, вероятно, самая простая замена.   -  person Joachim Sauer    schedule 18.09.2019


Ответы (1)


Итак, интерфейс AutoCloseable с try-with-resources кажется вам лучшим вариантом на сегодняшний день. Этот вариант финализации, по моему мнению, самый простой в реализации, но, конечно, он может варьироваться в зависимости от сложности каждого проекта.

класс A должен реализовать AutoCloseable class A implements AutoCloseable, и все места, где создается его объект, должны быть заключены в попытку, например try (A obj = new A())

Теперь идите дальше и переопределите метод закрытия, предоставляемый AutoCloseable, и вызовите destroy() изнутри.

class A implements AutoCloseable
{
    @Override
    public void close()
    {
        //log messages
        destroy();
    }
}

class X
{
    // suppose creating object of A within some method
    // enclose in try
    try ( A obj = new A ())
    {
        //use obj
    }
    // at the end of scope, the close() method of A will be called.
}
person aashima    schedule 24.09.2019