Подтвердить что ты не робот

Почему нет объекта StrongReference?

Я реализую некоторое поведение, которое может извлечь выгоду из использования слабых ссылок некоторое время. Я хотел бы, чтобы пользователь класса мог указать на время строительства, является ли это так или нет. Поскольку WeakReference extends Reference на первый взгляд кажется, что я мог бы что-то сделать (это макет, а не то, что я на самом деле пытаюсь сделать):

public class Container<T> {
    private boolean useWeakRef;
    private Reference<T> ref;

    public Container(boolean isWeak) {
        useWeakRef = isWeak;
    }

    public void store(T val) {
        if(useWeakRef) {
            ref = new WeakReference<>(val);
        } else {
            ref = new StrongReference<>(val);
        }
    }

    // May return null
    public T get() {
        return ref.get();
    }
}

Однако нет класса StrongReference и в соответствии с Reference javadocs:

Поскольку эталонные объекты реализованы в тесном сотрудничестве с сборщиком мусора, этот класс не может быть подклассифицирован напрямую.

Поэтому я не могу создать свой собственный подкласс Reference, который содержит сильную (то есть нормальную) ссылку на объект. Это означает, что невозможно создать класс, который скрывает, использует ли он слабые (или мягкие) ссылки от вызывающего.

Я действительно не понимаю, почему этот класс не существует, объект StrongReference должен просто всегда возвращать объект из get(), если не был вызван clear(). Почему это отсутствует? Является ли StrongReference несовместимым с Reference каким-то образом? Это значительно упростило бы создание общих объектов опорных держателей.

4b9b3361

Ответ 1

В Guava LocalCache используется класс StrongValueReference, который воспроизводит то, что мне нужно для класса StrongReference. Хотя это слишком плохо, Guava не раскрывает это как открытый класс, я принимаю это как подтверждение того, что это недостающая функция от JDK, и что это нормально, чтобы реплицировать ее, когда это необходимо.

Тем не менее, большинство случаев использования, которые должны абстрагироваться от типа ссылок, с которыми они работают, скорее всего, смогут использовать Guava Cache поведение, как и я. Я бы посоветовал всем, кто встретил этот вопрос, изучить существующие механизмы кэширования в Гуаве, прежде чем изобретать это абстрактное поведение ссылок.

Ответ 2

Когда мне нужно это сделать, я просто создал настраиваемый интерфейс ссылок и тривиальный подкласс WeakReference. это раздражает, но это примерно так же хорошо, как вы можете.

public interface MyReference<T> {
  public T get();
}

public class MyWeakReference<T> extends WeakReference<T> implements MyReference<T> {
}

public class MyStrongReference<T> implements MyReference<T> {
  // obvious implementation here ...
}

UPDATE:

чтобы понять, я понятия не имею, почему это не было включено в jdk в первую очередь (я тоже хотел, чтобы это было), однако я считаю, что это разумное решение.

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

Ответ 3

Вы не можете подклассифицировать ссылку, потому что у нее нет публичных/защищенных конструкторов. Но есть обходное решение:

class StrongReference<T> extends WeakReference<T> {
    private final T referent;

    StrongReference(T referent) {
        super(null);
        this.referent = referent;
    }

    @Override
    public T get() {
        return referent;
    }

    // implement other methods
}