Как я могу удалить защищенный метод void finalize () из моего кода - PullRequest
1 голос
/ 02 мая 2019

Эта проблема с Java-методом защищена void finalize (), я пытался посмотреть на прошлые вопросы по этому поводу, но до сих пор не могу понять, как ее решить, Так что один из моих классов проекта вызывает этот метод finalize (), который устарел из Java 9, возможно, они удалят его в следующем выпуске, поэтому моя компания хочет решить эту проблему, и я получил работу над этой частью, что является моей неудачей , Может кто-нибудь предложить мне, как я могу это исправить, решение простое, просто удалите этот метод из класса, но никто не разрешит мне сделать это, потому что они не хотят рисковать. Поэтому мне нужно решение для этого,

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

private DiskCache dc;

  public void delete(DiskCacheItem item)
  {
    File f = file(item);
    if (f != null)
    {
      log.debug("Delete " + f + ": " + f.delete());
    }
    files.remove(item);
    items.remove(item);
  }

private void validate()
  {
    dc.validate(this);
  } 


public void delete()
  {
    validate();
    dc.delete(this);
  }


protected void finalize()
  {
    try { delete(); } catch (Exception e) { }
  }

Ответы [ 2 ]

1 голос
/ 08 мая 2019

Понятно, что вы просто сопротивляетесь удалению метода finalize(). В конце концов, он делает некоторую полезную очистку. Вопрос в том, чем его заменить.

Создание элемента AutoCloseable может помочь, хотя это работает, только если элемент используется в пределах одной лексической области. Это позволит вам использовать try-with-resources. Если элемент не используется в лексической области, например, если он подключен к нескольким структурам данных, вы не сможете использовать try-with-resources. Здесь вам может потребоваться выполнить некоторые действия по очистке после того, как элемент станет недоступным.

Предпочтительная замена для финализации - использовать что-то вроде WeakReference. Нормальные ссылки - это "сильные" ссылки. Когда все сильные ссылки ушли, оставив только слабые ссылки, предмет становится «слабо доступным». Это ставит в очередь ссылку на очередь ссылок; по сути, это событие, которое говорит, что «предмет больше недоступен», и действие, которое необходимо предпринять при получении этого события, состоит в выполнении некоторого действия очистки.

Этот тип обработки ссылок может быть неудобным, поэтому существует другой механизм, называемый Cleaner, который может быть проще в использовании.

То, что сделало финализацию удобной, заключается в том, что метод finalize() находится на самом объекте, который должен быть собран. Среди проблем с финализацией является то, что это «воскрешает» объект, создавая новую сильную ссылку на него.

Уловка со ссылкой или более чистой обработкой заключается в том, что вам нужно отслеживать вещи, которые необходимо очистить, без сохранения ссылки на объект, с которым он связан. В вашем случае у вас есть DiskCacheItem, который, очевидно, содержится в DiskCache. Если экземпляр DiskCacheItem собирается собирать мусор, вы хотите удалить его из DiskCache. Трудно сказать из вашего кода, но похоже, что действие по очистке заключается в удалении объекта File, который может быть связан с DiskCacheItem. Если так, вот что нужно сделать:

  1. Создайте экземпляр Cleaner, который будет отвечать за выполнение действий по очистке.

  2. Создайте класс состояния, который содержит очищаемый материал, в данном случае File.

  3. Когда к DiskCache добавляется DiskCacheItem, создайте экземпляр класса состояния и зарегистрируйте его в Cleaner, связав его с действием очистки. В этом случае действие очистки заключается в удалении файла. Это возвращает экземпляр Cleanable.

  4. Если в DiskCacheItem есть явное действие «закрыть» или «удалить», вызовите его clean() для соответствующего очищаемого объекта. Это немедленно вызовет действие очистки.

  5. Когда-нибудь в будущем, если DiskCacheItem не будет удален явно и все сильные ссылки на него будут удалены, он станет фантомно достижимым. Это заставит Cleaner вызывать действие очистки.

Это эффективно заменяет финализацию и метод finalize(), хотя для этого вам придется немного перестроить структуры данных.

После всего этого, какой смысл заменять финализацию механизмом Cleaner / Cleanable? Во-первых, вы можете явно очистить Cleanable. Когда он в конце концов становится недоступным, это просто сбор мусора. Никакой дополнительной обработки не делается. С помощью finalization, даже если финализуемый объект уже был логически очищен, JVM все равно необходимо запустить метод finalize (). Во-вторых, для завершения требуется дополнительный проход GC, чтобы гарантировать, что объект не был «воскрешен». При обработке ссылок и Cleaner нет возможности «воскресить» объект. В-третьих, финализация хрупка, и трудно правильно реализовать метод finalize ().

1 голос
/ 02 мая 2019

Для таких классов, у которых есть ресурсы, которые требуют специальной обработки после использования, должен быть реализован интерфейс с автоматическим закрытием. Он дает метод close (), в который вы можете поместить код удаления. Затем его можно использовать при попытке с шаблоном ресурсов следующим образом:

try(YourClass yourObject = new YourClass()) {
    // do work with yourObject
}

Компилятор автоматически поместит блок finally в конец и вызовет yourObject.close(); внутри него для безопасной очистки ресурсов.

Редактировать Пример класса будет выглядеть так:

class MyClass implements AutoCloseable {
    // create resources

    @Override
    public void close() throws Exception {
        // delete resources here
    }
}
...